2007-06-24 21:19:22 +04:00
/**********************************************************************
2008-11-14 14:31:10 +03:00
vm_insnhelper . c - instruction helper functions .
2007-06-24 21:19:22 +04:00
$ Author $
Copyright ( C ) 2007 Koichi Sasada
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* finish iseq array */
# include "insns.inc"
2008-01-17 20:06:51 +03:00
# include <math.h>
2007-06-24 21:19:22 +04:00
/* control stack frame */
2007-08-06 15:36:30 +04:00
# ifndef INLINE
# define INLINE inline
# endif
2009-01-19 06:03:09 +03:00
static rb_control_frame_t * vm_get_ruby_level_caller_cfp ( rb_thread_t * th , rb_control_frame_t * cfp ) ;
2007-06-24 21:19:22 +04:00
static inline rb_control_frame_t *
2008-05-22 20:19:14 +04:00
vm_push_frame ( rb_thread_t * th , const rb_iseq_t * iseq ,
VALUE type , VALUE self , VALUE specval ,
const VALUE * pc , VALUE * sp , VALUE * lfp ,
int local_size )
2007-06-24 21:19:22 +04:00
{
2009-11-07 05:45:08 +03:00
rb_control_frame_t * const cfp = th - > cfp - 1 ;
2007-06-24 21:19:22 +04:00
int i ;
2009-11-07 14:59:16 +03:00
if ( ( void * ) ( sp + local_size ) > = ( void * ) cfp ) {
rb_exc_raise ( sysstack_error ) ;
}
2009-11-07 05:45:08 +03:00
th - > cfp = cfp ;
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
/* setup vm value stack */
2009-02-22 17:23:33 +03:00
2007-06-24 21:19:22 +04:00
/* nil initialize */
for ( i = 0 ; i < local_size ; i + + ) {
* sp = Qnil ;
sp + + ;
}
/* set special val */
* sp = GC_GUARDED_PTR ( specval ) ;
if ( lfp = = 0 ) {
lfp = sp ;
}
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
/* setup vm control frame stack */
2008-05-19 22:47:56 +04:00
cfp - > pc = ( VALUE * ) pc ;
2007-06-24 21:19:22 +04:00
cfp - > sp = sp + 1 ;
cfp - > bp = sp + 1 ;
2008-05-19 22:47:56 +04:00
cfp - > iseq = ( rb_iseq_t * ) iseq ;
2007-11-09 04:29:24 +03:00
cfp - > flag = type ;
2007-06-24 21:19:22 +04:00
cfp - > self = self ;
cfp - > lfp = lfp ;
2008-05-21 19:18:15 +04:00
cfp - > dfp = sp ;
2007-06-24 21:19:22 +04:00
cfp - > proc = 0 ;
2010-05-05 21:51:21 +04:00
cfp - > me = 0 ;
2007-06-24 21:19:22 +04:00
# define COLLECT_PROFILE 0
# if COLLECT_PROFILE
cfp - > prof_time_self = clock ( ) ;
cfp - > prof_time_chld = 0 ;
# endif
2007-08-12 23:12:55 +04:00
if ( VMDEBUG = = 2 ) {
SDR ( ) ;
}
2007-06-24 21:19:22 +04:00
return cfp ;
}
static inline void
2008-05-22 20:19:14 +04:00
vm_pop_frame ( rb_thread_t * th )
2007-06-24 21:19:22 +04:00
{
# if COLLECT_PROFILE
rb_control_frame_t * cfp = th - > cfp ;
if ( RUBY_VM_NORMAL_ISEQ_P ( cfp - > iseq ) ) {
VALUE current_time = clock ( ) ;
rb_control_frame_t * cfp = th - > cfp ;
cfp - > prof_time_self = current_time - cfp - > prof_time_self ;
( cfp + 1 ) - > prof_time_chld + = cfp - > prof_time_self ;
cfp - > iseq - > profile . count + + ;
cfp - > iseq - > profile . time_cumu = cfp - > prof_time_self ;
cfp - > iseq - > profile . time_self = cfp - > prof_time_self - cfp - > prof_time_chld ;
}
else if ( 0 /* c method? */ ) {
}
# endif
th - > cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( th - > cfp ) ;
2007-08-12 23:12:55 +04:00
if ( VMDEBUG = = 2 ) {
SDR ( ) ;
}
2007-06-24 21:19:22 +04:00
}
/* method dispatch */
2010-05-04 08:00:20 +04:00
NORETURN ( static void argument_error ( const rb_iseq_t * iseq , int miss_argc , int correct_argc ) ) ;
2010-05-04 07:50:39 +04:00
static void
argument_error ( const rb_iseq_t * iseq , int miss_argc , int correct_argc )
{
VALUE mesg = rb_sprintf ( " wrong number of arguments (%d for %d) " , miss_argc , correct_argc ) ;
VALUE exc = rb_exc_new3 ( rb_eArgError , mesg ) ;
VALUE bt = rb_make_backtrace ( ) ;
VALUE err_line = 0 ;
if ( iseq ) {
int line_no = 1 ;
if ( iseq - > insn_info_size ) {
line_no = iseq - > insn_info_table [ 0 ] . line_no ;
}
err_line = rb_sprintf ( " %s:%d:in `%s' " ,
RSTRING_PTR ( iseq - > filename ) ,
line_no , RSTRING_PTR ( iseq - > name ) ) ;
rb_funcall ( bt , rb_intern ( " unshift " ) , 1 , err_line ) ;
}
rb_funcall ( exc , rb_intern ( " set_backtrace " ) , 1 , bt ) ;
rb_exc_raise ( exc ) ;
}
2009-11-07 06:51:39 +03:00
# define VM_CALLEE_SETUP_ARG(ret, th, iseq, orig_argc, orig_argv, block) \
2008-06-06 18:48:07 +04:00
if ( LIKELY ( iseq - > arg_simple & 0x01 ) ) { \
/* simple check */ \
if ( orig_argc ! = iseq - > argc ) { \
2010-05-04 07:50:39 +04:00
argument_error ( iseq , orig_argc , iseq - > argc ) ; \
2008-06-06 18:48:07 +04:00
} \
2009-11-07 06:51:39 +03:00
ret = 0 ; \
2008-06-06 18:48:07 +04:00
} \
else { \
2009-11-07 06:51:39 +03:00
ret = vm_callee_setup_arg_complex ( th , iseq , orig_argc , orig_argv , block ) ; \
2008-06-06 18:48:07 +04:00
}
2008-05-21 19:18:15 +04:00
static inline int
2008-06-06 18:48:07 +04:00
vm_callee_setup_arg_complex ( rb_thread_t * th , const rb_iseq_t * iseq ,
int orig_argc , VALUE * orig_argv ,
2009-11-07 06:51:39 +03:00
const rb_block_t * * block )
2007-06-24 21:19:22 +04:00
{
const int m = iseq - > argc ;
2008-06-06 18:48:07 +04:00
int argc = orig_argc ;
VALUE * argv = orig_argv ;
2009-05-20 13:58:29 +04:00
rb_num_t opt_pc = 0 ;
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
th - > mark_stack_len = argc + iseq - > arg_size ;
/* mandatory */
if ( argc < ( m + iseq - > arg_post_len ) ) { /* check with post arg */
2010-05-04 07:50:39 +04:00
argument_error ( iseq , argc , m + iseq - > arg_post_len ) ;
2007-06-24 21:19:22 +04:00
}
2008-05-21 19:18:15 +04:00
2008-06-06 18:48:07 +04:00
argv + = m ;
argc - = m ;
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
/* post arguments */
if ( iseq - > arg_post_len ) {
if ( ! ( orig_argc < iseq - > arg_post_start ) ) {
VALUE * new_argv = ALLOCA_N ( VALUE , argc ) ;
MEMCPY ( new_argv , argv , VALUE , argc ) ;
argv = new_argv ;
2007-06-24 21:19:22 +04:00
}
2008-06-06 18:48:07 +04:00
MEMCPY ( & orig_argv [ iseq - > arg_post_start ] , & argv [ argc - = iseq - > arg_post_len ] ,
VALUE , iseq - > arg_post_len ) ;
}
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
/* opt arguments */
if ( iseq - > arg_opts ) {
const int opts = iseq - > arg_opts - 1 /* no opt */ ;
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
if ( iseq - > arg_rest = = - 1 & & argc > opts ) {
2010-05-04 07:50:39 +04:00
argument_error ( iseq , orig_argc , m + opts + iseq - > arg_post_len ) ;
2007-06-24 21:19:22 +04:00
}
2008-06-06 18:48:07 +04:00
if ( argc > opts ) {
argc - = opts ;
argv + = opts ;
opt_pc = iseq - > arg_opt_table [ opts ] ; /* no opt */
2007-06-24 21:19:22 +04:00
}
2008-06-06 18:48:07 +04:00
else {
int i ;
for ( i = argc ; i < opts ; i + + ) {
orig_argv [ i + m ] = Qnil ;
}
opt_pc = iseq - > arg_opt_table [ argc ] ;
2007-08-18 08:17:39 +04:00
argc = 0 ;
2007-06-24 21:19:22 +04:00
}
2008-06-06 18:48:07 +04:00
}
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
/* rest arguments */
if ( iseq - > arg_rest ! = - 1 ) {
orig_argv [ iseq - > arg_rest ] = rb_ary_new4 ( argc , argv ) ;
argc = 0 ;
}
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
/* block arguments */
if ( block & & iseq - > arg_block ! = - 1 ) {
VALUE blockval = Qnil ;
const rb_block_t * blockptr = * block ;
2007-08-18 08:17:39 +04:00
2008-06-06 18:48:07 +04:00
if ( argc ! = 0 ) {
2010-05-04 07:50:39 +04:00
argument_error ( iseq , orig_argc , m + iseq - > arg_post_len ) ;
2008-06-06 18:48:07 +04:00
}
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
if ( blockptr ) {
/* make Proc object */
if ( blockptr - > proc = = 0 ) {
rb_proc_t * proc ;
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
blockval = rb_vm_make_proc ( th , blockptr , rb_cProc ) ;
2008-06-06 18:48:07 +04:00
GetProcPtr ( blockval , proc ) ;
* block = & proc - > block ;
}
else {
blockval = blockptr - > proc ;
}
2007-06-24 21:19:22 +04:00
}
2007-12-09 08:56:00 +03:00
2008-06-06 18:48:07 +04:00
orig_argv [ iseq - > arg_block ] = blockval ; /* Proc or nil */
2007-06-24 21:19:22 +04:00
}
2008-06-06 18:48:07 +04:00
th - > mark_stack_len = 0 ;
2009-05-20 13:58:29 +04:00
return ( int ) opt_pc ;
2007-06-24 21:19:22 +04:00
}
static inline int
2008-05-22 20:19:14 +04:00
caller_setup_args ( const rb_thread_t * th , rb_control_frame_t * cfp , VALUE flag ,
int argc , rb_iseq_t * blockiseq , rb_block_t * * block )
2007-06-24 21:19:22 +04:00
{
rb_block_t * blockptr = 0 ;
2007-06-25 20:05:17 +04:00
if ( block ) {
2007-06-24 22:40:13 +04:00
if ( flag & VM_CALL_ARGS_BLOCKARG_BIT ) {
rb_proc_t * po ;
VALUE proc ;
2007-06-24 21:19:22 +04:00
2007-06-24 22:40:13 +04:00
proc = * ( - - cfp - > sp ) ;
2007-06-24 21:19:22 +04:00
2007-06-24 22:40:13 +04:00
if ( proc ! = Qnil ) {
2007-06-24 21:19:22 +04:00
if ( ! rb_obj_is_proc ( proc ) ) {
2007-07-03 23:59:59 +04:00
VALUE b = rb_check_convert_type ( proc , T_DATA , " Proc " , " to_proc " ) ;
2008-08-13 12:32:53 +04:00
if ( NIL_P ( b ) | | ! rb_obj_is_proc ( b ) ) {
2007-06-24 22:40:13 +04:00
rb_raise ( rb_eTypeError ,
" wrong argument type %s (expected Proc) " ,
rb_obj_classname ( proc ) ) ;
}
2007-07-03 23:59:59 +04:00
proc = b ;
2007-06-24 21:19:22 +04:00
}
2007-06-24 22:40:13 +04:00
GetProcPtr ( proc , po ) ;
blockptr = & po - > block ;
RUBY_VM_GET_BLOCK_PTR_IN_CFP ( cfp ) - > proc = proc ;
* block = blockptr ;
2007-06-24 21:19:22 +04:00
}
2007-06-24 22:40:13 +04:00
}
else if ( blockiseq ) {
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP ( cfp ) ;
blockptr - > iseq = blockiseq ;
blockptr - > proc = 0 ;
2007-06-24 21:19:22 +04:00
* block = blockptr ;
}
}
/* expand top of stack? */
if ( flag & VM_CALL_ARGS_SPLAT_BIT ) {
VALUE ary = * ( cfp - > sp - 1 ) ;
VALUE * ptr ;
int i ;
2007-12-01 08:20:06 +03:00
VALUE tmp = rb_check_convert_type ( ary , T_ARRAY , " Array " , " to_a " ) ;
2007-06-24 21:19:22 +04:00
if ( NIL_P ( tmp ) ) {
/* do nothing */
}
else {
2009-05-20 13:58:29 +04:00
long len = RARRAY_LEN ( tmp ) ;
2007-06-24 21:19:22 +04:00
ptr = RARRAY_PTR ( tmp ) ;
cfp - > sp - = 1 ;
CHECK_STACK_OVERFLOW ( cfp , len ) ;
for ( i = 0 ; i < len ; i + + ) {
* cfp - > sp + + = ptr [ i ] ;
}
argc + = i - 1 ;
}
}
return argc ;
}
static inline VALUE
2008-05-22 20:19:14 +04:00
call_cfunc ( VALUE ( * func ) ( ) , VALUE recv ,
int len , int argc , const VALUE * argv )
2007-06-24 21:19:22 +04:00
{
/* printf("len: %d, argc: %d\n", len, argc); */
if ( len > = 0 & & argc ! = len ) {
rb_raise ( rb_eArgError , " wrong number of arguments(%d for %d) " ,
argc , len ) ;
}
switch ( len ) {
case - 2 :
return ( * func ) ( recv , rb_ary_new4 ( argc , argv ) ) ;
break ;
case - 1 :
return ( * func ) ( argc , argv , recv ) ;
break ;
case 0 :
return ( * func ) ( recv ) ;
break ;
case 1 :
return ( * func ) ( recv , argv [ 0 ] ) ;
break ;
case 2 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] ) ;
break ;
case 3 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] ) ;
break ;
case 4 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] ) ;
break ;
case 5 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ) ;
break ;
case 6 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] ) ;
break ;
case 7 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] ) ;
break ;
case 8 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] ) ;
break ;
case 9 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] ) ;
break ;
case 10 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] ) ;
break ;
case 11 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] ,
argv [ 10 ] ) ;
break ;
case 12 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] ,
argv [ 10 ] , argv [ 11 ] ) ;
break ;
case 13 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] , argv [ 10 ] ,
argv [ 11 ] , argv [ 12 ] ) ;
break ;
case 14 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] , argv [ 10 ] ,
argv [ 11 ] , argv [ 12 ] , argv [ 13 ] ) ;
break ;
case 15 :
return ( * func ) ( recv , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ,
argv [ 5 ] , argv [ 6 ] , argv [ 7 ] , argv [ 8 ] , argv [ 9 ] , argv [ 10 ] ,
argv [ 11 ] , argv [ 12 ] , argv [ 13 ] , argv [ 14 ] ) ;
break ;
default :
rb_raise ( rb_eArgError , " too many arguments(%d) " , len ) ;
2009-07-15 18:59:41 +04:00
return Qundef ; /* not reached */
2007-06-24 21:19:22 +04:00
}
}
static inline VALUE
2008-05-22 20:19:14 +04:00
vm_call_cfunc ( rb_thread_t * th , rb_control_frame_t * reg_cfp ,
2010-01-24 16:52:32 +03:00
int num , VALUE recv , const rb_block_t * blockptr ,
2009-07-15 18:59:41 +04:00
const rb_method_entry_t * me )
2007-06-24 21:19:22 +04:00
{
2009-07-10 05:25:26 +04:00
VALUE val = 0 ;
2009-08-28 06:45:41 +04:00
const rb_method_definition_t * def = me - > def ;
2010-01-24 16:52:32 +03:00
rb_control_frame_t * cfp ;
2007-06-24 21:19:22 +04:00
2010-01-24 16:52:32 +03:00
EXEC_EVENT_HOOK ( th , RUBY_EVENT_C_CALL , recv , me - > called_id , me - > klass ) ;
2009-07-15 18:59:41 +04:00
2010-01-24 16:52:32 +03:00
cfp = vm_push_frame ( th , 0 , VM_FRAME_MAGIC_CFUNC ,
recv , ( VALUE ) blockptr , 0 , reg_cfp - > sp , 0 , 1 ) ;
cfp - > me = me ;
reg_cfp - > sp - = num + 1 ;
2007-06-24 21:19:22 +04:00
2010-01-24 16:52:32 +03:00
val = call_cfunc ( def - > body . cfunc . func , recv , ( int ) def - > body . cfunc . argc , num , reg_cfp - > sp + 1 ) ;
2007-06-24 21:19:22 +04:00
2010-01-24 16:52:32 +03:00
if ( reg_cfp ! = th - > cfp + 1 ) {
rb_bug ( " cfp consistency error - send " ) ;
}
2007-06-24 21:19:22 +04:00
2010-01-24 16:52:32 +03:00
vm_pop_frame ( th ) ;
* 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
2008-06-11 01:46:43 +04:00
2010-01-24 16:52:32 +03:00
EXEC_EVENT_HOOK ( th , RUBY_EVENT_C_RETURN , recv , me - > called_id , me - > klass ) ;
2007-06-24 21:19:22 +04:00
return val ;
}
static inline VALUE
2009-07-15 18:59:41 +04:00
vm_call_bmethod ( rb_thread_t * th , VALUE recv , int argc , const VALUE * argv ,
const rb_block_t * blockptr , const rb_method_entry_t * me )
2007-06-24 21:19:22 +04:00
{
rb_proc_t * proc ;
VALUE val ;
/* control block frame */
2010-05-05 21:51:21 +04:00
th - > passed_me = me ;
2007-06-24 21:19:22 +04:00
2009-08-28 06:45:41 +04:00
GetProcPtr ( me - > def - > body . proc , proc ) ;
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
val = rb_vm_invoke_proc ( th , proc , recv , argc , argv , blockptr ) ;
2007-06-24 21:19:22 +04:00
return val ;
}
2009-02-22 04:43:59 +03:00
static inline void
vm_method_missing_args ( rb_thread_t * th , VALUE * argv ,
2009-07-15 18:59:41 +04:00
int num , const rb_block_t * blockptr , int opt )
2007-06-24 21:19:22 +04:00
{
2008-05-21 19:18:15 +04:00
rb_control_frame_t * const reg_cfp = th - > cfp ;
2008-09-02 19:23:49 +04:00
MEMCPY ( argv , STACK_ADDR_FROM_TOP ( num + 1 ) , VALUE , num + 1 ) ;
2007-06-24 21:19:22 +04:00
th - > method_missing_reason = opt ;
th - > passed_block = blockptr ;
POPN ( num + 1 ) ;
2009-02-22 04:43:59 +03:00
}
static inline VALUE
vm_method_missing ( rb_thread_t * th , ID id , VALUE recv ,
2009-07-15 18:59:41 +04:00
int num , const rb_block_t * blockptr , int opt )
2009-02-22 04:43:59 +03:00
{
VALUE * argv = ALLOCA_N ( VALUE , num + 1 ) ;
vm_method_missing_args ( th , argv , num , blockptr , opt ) ;
argv [ 0 ] = ID2SYM ( id ) ;
return rb_funcall2 ( recv , idMethodMissing , num + 1 , argv ) ;
2007-06-24 21:19:22 +04:00
}
static inline void
2010-05-29 22:51:39 +04:00
vm_setup_method ( rb_thread_t * th , rb_control_frame_t * cfp ,
VALUE recv , int argc , const rb_block_t * blockptr , VALUE flag ,
2009-07-15 18:59:41 +04:00
const rb_method_entry_t * me )
2007-06-24 21:19:22 +04:00
{
int opt_pc , i ;
2007-12-09 08:56:00 +03:00
VALUE * sp , * rsp = cfp - > sp - argc ;
2009-08-28 06:45:41 +04:00
rb_iseq_t * iseq = me - > def - > body . iseq ;
2007-06-24 21:19:22 +04:00
2009-11-07 06:51:39 +03:00
VM_CALLEE_SETUP_ARG ( opt_pc , th , iseq , argc , rsp , & blockptr ) ;
2007-06-24 21:19:22 +04:00
/* stack overflow check */
2007-12-18 16:14:32 +03:00
CHECK_STACK_OVERFLOW ( cfp , iseq - > stack_max ) ;
sp = rsp + iseq - > arg_size ;
2007-06-24 21:19:22 +04:00
2007-08-26 01:05:20 +04:00
if ( LIKELY ( ! ( flag & VM_CALL_TAILCALL_BIT ) ) ) {
2009-06-24 04:54:31 +04:00
if ( 0 ) printf ( " local_size: %d, arg_size: %d \n " ,
2007-08-26 01:05:20 +04:00
iseq - > local_size , iseq - > arg_size ) ;
2007-06-24 21:19:22 +04:00
/* clear local variables */
for ( i = 0 ; i < iseq - > local_size - iseq - > arg_size ; i + + ) {
* sp + + = Qnil ;
}
vm_push_frame ( th , iseq ,
* 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
2008-06-11 01:46:43 +04:00
VM_FRAME_MAGIC_METHOD , recv , ( VALUE ) blockptr ,
2007-06-24 21:19:22 +04:00
iseq - > iseq_encoded + opt_pc , sp , 0 , 0 ) ;
2007-08-26 01:05:20 +04:00
cfp - > sp = rsp - 1 /* recv */ ;
2007-06-24 21:19:22 +04:00
}
else {
2007-08-26 01:05:20 +04:00
VALUE * p_rsp ;
2008-05-21 19:18:15 +04:00
th - > cfp + + ; /* pop cf */
2007-08-26 01:05:20 +04:00
p_rsp = th - > cfp - > sp ;
/* copy arguments */
for ( i = 0 ; i < ( sp - rsp ) ; i + + ) {
p_rsp [ i ] = rsp [ i ] ;
}
sp - = rsp - p_rsp ;
2007-06-24 21:19:22 +04:00
/* clear local variables */
for ( i = 0 ; i < iseq - > local_size - iseq - > arg_size ; i + + ) {
* sp + + = Qnil ;
}
vm_push_frame ( th , iseq ,
* 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
2008-06-11 01:46:43 +04:00
VM_FRAME_MAGIC_METHOD , recv , ( VALUE ) blockptr ,
2007-06-24 21:19:22 +04:00
iseq - > iseq_encoded + opt_pc , sp , 0 , 0 ) ;
}
}
static inline VALUE
2009-07-15 18:59:41 +04:00
vm_call_method ( rb_thread_t * th , rb_control_frame_t * cfp ,
int num , const rb_block_t * blockptr , VALUE flag ,
ID id , const rb_method_entry_t * me , VALUE recv )
2007-06-24 21:19:22 +04:00
{
VALUE val ;
start_method_dispatch :
2009-07-15 18:59:41 +04:00
if ( me ! = 0 ) {
if ( ( me - > flag = = 0 ) ) {
2007-08-26 00:56:51 +04:00
normal_method_dispatch :
2009-08-28 06:45:41 +04:00
switch ( me - > def - > type ) {
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_ISEQ : {
vm_setup_method ( th , cfp , recv , num , blockptr , flag , me ) ;
2008-01-17 19:48:18 +03:00
return Qundef ;
2007-08-26 00:56:51 +04:00
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_NOTIMPLEMENTED :
case VM_METHOD_TYPE_CFUNC : {
2010-01-24 16:52:32 +03:00
val = vm_call_cfunc ( th , cfp , num , recv , blockptr , me ) ;
2008-01-17 19:48:18 +03:00
break ;
2007-08-26 00:56:51 +04:00
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_ATTRSET : {
if ( num ! = 1 ) {
rb_raise ( rb_eArgError , " wrong number of arguments (%d for 1) " , num ) ;
}
2010-03-22 14:44:01 +03:00
val = rb_ivar_set ( recv , me - > def - > body . attr . id , * ( cfp - > sp - 1 ) ) ;
2008-01-17 19:48:18 +03:00
cfp - > sp - = 2 ;
break ;
2007-08-26 00:56:51 +04:00
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_IVAR : {
2008-01-17 19:48:18 +03:00
if ( num ! = 0 ) {
2009-07-15 18:59:41 +04:00
rb_raise ( rb_eArgError , " wrong number of arguments (%d for 0) " , num ) ;
2008-01-17 19:48:18 +03:00
}
2010-03-22 14:44:01 +03:00
val = rb_attr_get ( recv , me - > def - > body . attr . id ) ;
2008-01-17 19:48:18 +03:00
cfp - > sp - = 1 ;
break ;
2007-08-26 00:56:51 +04:00
}
2009-09-28 07:09:16 +04:00
case VM_METHOD_TYPE_MISSING : {
VALUE * argv = ALLOCA_N ( VALUE , num + 1 ) ;
argv [ 0 ] = ID2SYM ( me - > def - > original_id ) ;
MEMCPY ( argv + 1 , cfp - > sp - num , VALUE , num ) ;
cfp - > sp + = - num - 1 ;
val = rb_funcall2 ( recv , rb_intern ( " method_missing " ) , num + 1 , argv ) ;
break ;
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_BMETHOD : {
2008-08-29 12:24:51 +04:00
VALUE * argv = ALLOCA_N ( VALUE , num ) ;
MEMCPY ( argv , cfp - > sp - num , VALUE , num ) ;
2008-01-17 19:48:18 +03:00
cfp - > sp + = - num - 1 ;
2009-07-15 18:59:41 +04:00
val = vm_call_bmethod ( th , recv , num , argv , blockptr , me ) ;
2008-01-17 19:48:18 +03:00
break ;
2007-08-26 00:56:51 +04:00
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_ZSUPER : {
VALUE klass = RCLASS_SUPER ( me - > klass ) ;
me = rb_method_entry ( klass , id ) ;
2008-01-17 19:48:18 +03:00
2009-07-15 18:59:41 +04:00
if ( me ! = 0 ) {
2008-01-17 19:48:18 +03:00
goto normal_method_dispatch ;
}
else {
goto start_method_dispatch ;
}
2007-08-26 00:56:51 +04:00
}
2009-07-15 18:59:41 +04:00
case VM_METHOD_TYPE_OPTIMIZED : {
2009-08-28 06:45:41 +04:00
switch ( me - > def - > body . optimize_type ) {
2009-07-26 13:27:45 +04:00
case OPTIMIZED_METHOD_TYPE_SEND : {
rb_control_frame_t * reg_cfp = cfp ;
rb_num_t i = num - 1 ;
VALUE sym ;
if ( num = = 0 ) {
rb_raise ( rb_eArgError , " no method name given " ) ;
2009-07-15 18:59:41 +04:00
}
2009-07-26 13:27:45 +04:00
sym = TOPN ( i ) ;
id = SYMBOL_P ( sym ) ? SYM2ID ( sym ) : rb_to_id ( sym ) ;
/* shift arguments */
if ( i > 0 ) {
MEMMOVE ( & TOPN ( i ) , & TOPN ( i - 1 ) , VALUE , i ) ;
2009-07-15 18:59:41 +04:00
}
2009-07-26 13:27:45 +04:00
me = rb_method_entry ( CLASS_OF ( recv ) , id ) ;
num - = 1 ;
DEC_SP ( 1 ) ;
2009-07-28 22:38:59 +04:00
flag | = VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT ;
2009-07-26 13:27:45 +04:00
goto start_method_dispatch ;
2009-07-15 18:59:41 +04:00
}
2009-07-26 13:27:45 +04:00
case OPTIMIZED_METHOD_TYPE_CALL : {
rb_proc_t * proc ;
int argc = num ;
VALUE * argv = ALLOCA_N ( VALUE , num ) ;
GetProcPtr ( recv , proc ) ;
MEMCPY ( argv , cfp - > sp - num , VALUE , num ) ;
cfp - > sp - = num + 1 ;
val = rb_vm_invoke_proc ( th , proc , proc - > block . self , argc , argv , blockptr ) ;
break ;
}
default :
rb_bug ( " eval_invoke_method: unsupported optimized method type (%d) " ,
2009-08-28 06:45:41 +04:00
me - > def - > body . optimize_type ) ;
2009-07-26 13:27:45 +04:00
}
break ;
2009-07-15 18:59:41 +04:00
}
2007-08-26 00:56:51 +04:00
default : {
2009-08-28 06:45:41 +04:00
rb_bug ( " eval_invoke_method: unsupported method type (%d) " , me - > def - > type ) ;
2008-01-17 19:48:18 +03:00
break ;
2007-08-26 00:56:51 +04:00
}
2007-08-17 16:25:47 +04:00
}
2007-06-24 21:19:22 +04:00
}
2007-08-26 00:56:51 +04:00
else {
int noex_safe ;
if ( ! ( flag & VM_CALL_FCALL_BIT ) & &
2009-07-15 18:59:41 +04:00
( me - > flag & NOEX_MASK ) & NOEX_PRIVATE ) {
2007-08-26 00:56:51 +04:00
int stat = NOEX_PRIVATE ;
2007-06-24 21:19:22 +04:00
2007-08-26 00:56:51 +04:00
if ( flag & VM_CALL_VCALL_BIT ) {
stat | = NOEX_VCALL ;
}
val = vm_method_missing ( th , id , recv , num , blockptr , stat ) ;
2007-08-17 16:25:47 +04:00
}
2009-07-28 22:38:59 +04:00
else if ( ! ( flag & VM_CALL_OPT_SEND_BIT ) & & ( me - > flag & NOEX_MASK ) & NOEX_PROTECTED ) {
2009-07-15 18:59:41 +04:00
VALUE defined_class = me - > klass ;
2007-08-26 00:56:51 +04:00
if ( TYPE ( defined_class ) = = T_ICLASS ) {
defined_class = RBASIC ( defined_class ) - > klass ;
}
2007-06-24 21:19:22 +04:00
2009-11-16 10:01:44 +03:00
if ( ! rb_obj_is_kind_of ( cfp - > self , defined_class ) ) {
2007-08-26 00:56:51 +04:00
val = vm_method_missing ( th , id , recv , num , blockptr , NOEX_PROTECTED ) ;
}
else {
goto normal_method_dispatch ;
}
}
2009-07-15 18:59:41 +04:00
else if ( ( noex_safe = NOEX_SAFE ( me - > flag ) ) > th - > safe_level & &
2007-08-26 00:56:51 +04:00
( noex_safe > 2 ) ) {
rb_raise ( rb_eSecurityError , " calling insecure method: %s " , rb_id2name ( id ) ) ;
2007-08-17 16:25:47 +04:00
}
else {
goto normal_method_dispatch ;
}
}
2007-06-24 21:19:22 +04:00
}
else {
2007-08-26 00:56:51 +04:00
/* method missing */
2009-02-22 04:43:59 +03:00
int stat = 0 ;
if ( flag & VM_CALL_VCALL_BIT ) {
stat | = NOEX_VCALL ;
}
if ( flag & VM_CALL_SUPER_BIT ) {
stat | = NOEX_SUPER ;
}
2007-08-26 00:56:51 +04:00
if ( id = = idMethodMissing ) {
2009-02-22 04:43:59 +03:00
VALUE * argv = ALLOCA_N ( VALUE , num ) ;
vm_method_missing_args ( th , argv , num - 1 , 0 , stat ) ;
rb_raise_method_missing ( th , num , argv , recv , stat ) ;
2007-08-26 00:56:51 +04:00
}
else {
val = vm_method_missing ( th , id , recv , num , blockptr , stat ) ;
2007-06-24 21:19:22 +04:00
}
}
RUBY_VM_CHECK_INTS ( ) ;
return val ;
}
2007-06-25 06:44:20 +04:00
/* yield */
2007-06-25 23:06:00 +04:00
static inline int
2008-05-21 19:18:15 +04:00
block_proc_is_lambda ( const VALUE procval )
2007-06-25 23:06:00 +04:00
{
rb_proc_t * proc ;
if ( procval ) {
GetProcPtr ( procval , proc ) ;
return proc - > is_lambda ;
}
else {
return 0 ;
}
}
2007-06-25 06:44:20 +04:00
static inline VALUE
* eval_method.c: renamed from vm_method.c. "vm_method.c" is included
by "vm.c".
* vm_eval.c: added. Some codes are moved from "eval.c"
* common.mk: fix for above changes.
* compile.c: make a vm_eval(0)
* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
blockinlining.c: fix for above changes. and do some refactoring.
this changes improve rb_yield() performance.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-24 21:50:17 +04:00
vm_yield_with_cfunc ( rb_thread_t * th , const rb_block_t * block ,
2008-06-09 19:52:51 +04:00
VALUE self , int argc , const VALUE * argv ,
2008-12-27 09:26:48 +03:00
const rb_block_t * blockargptr )
2007-06-25 06:44:20 +04:00
{
NODE * ifunc = ( NODE * ) block - > iseq ;
2008-06-10 20:33:51 +04:00
VALUE val , arg , blockarg ;
2007-06-25 23:06:00 +04:00
int lambda = block_proc_is_lambda ( block - > proc ) ;
2007-06-25 06:44:20 +04:00
2007-06-25 23:06:00 +04:00
if ( lambda ) {
2007-06-25 06:44:20 +04:00
arg = rb_ary_new4 ( argc , argv ) ;
}
2007-12-19 09:37:41 +03:00
else if ( argc = = 0 ) {
arg = Qnil ;
}
2007-06-25 06:44:20 +04:00
else {
2007-12-19 09:37:41 +03:00
arg = argv [ 0 ] ;
2007-06-25 06:44:20 +04:00
}
2008-12-27 09:26:48 +03:00
if ( blockargptr ) {
if ( blockargptr - > proc ) {
blockarg = blockargptr - > proc ;
2008-12-25 06:49:09 +03:00
}
else {
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
blockarg = rb_vm_make_proc ( th , blockargptr , rb_cProc ) ;
2008-12-25 06:49:09 +03:00
}
2008-06-10 20:33:51 +04:00
}
else {
blockarg = Qnil ;
}
2010-07-14 15:23:10 +04:00
vm_push_frame ( th , ( rb_iseq_t * ) ifunc , VM_FRAME_MAGIC_IFUNC ,
2007-06-25 06:44:20 +04:00
self , ( VALUE ) block - > dfp ,
0 , th - > cfp - > sp , block - > lfp , 1 ) ;
2008-06-10 20:33:51 +04:00
val = ( * ifunc - > nd_cfnc ) ( arg , ifunc - > nd_tval , argc , argv , blockarg ) ;
2007-06-25 06:44:20 +04:00
th - > cfp + + ;
return val ;
}
2008-10-27 16:35:46 +03:00
/*--
* @ brief on supplied all of optional , rest and post parameters .
* @ pre iseq is block style ( not lambda style )
*/
2007-06-25 06:44:20 +04:00
static inline int
2009-07-15 18:59:41 +04:00
vm_yield_setup_block_args_complex ( rb_thread_t * th , const rb_iseq_t * iseq ,
int argc , VALUE * argv )
2007-06-25 06:44:20 +04:00
{
2009-05-20 13:58:29 +04:00
rb_num_t opt_pc = 0 ;
2008-10-27 16:35:46 +03:00
int i ;
const int m = iseq - > argc ;
const int r = iseq - > arg_rest ;
int len = iseq - > arg_post_len ;
int start = iseq - > arg_post_start ;
int rsize = argc > m ? argc - m : 0 ; /* # of arguments which did not consumed yet */
int psize = rsize > len ? len : rsize ; /* # of post arguments */
int osize = 0 ; /* # of opt arguments */
VALUE ary ;
/* reserves arguments for post parameters */
rsize - = psize ;
if ( iseq - > arg_opts ) {
const int opts = iseq - > arg_opts - 1 ;
if ( rsize > opts ) {
osize = opts ;
opt_pc = iseq - > arg_opt_table [ opts ] ;
}
else {
osize = rsize ;
opt_pc = iseq - > arg_opt_table [ rsize ] ;
}
2007-06-25 06:44:20 +04:00
}
2008-10-27 16:35:46 +03:00
rsize - = osize ;
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
if ( 0 ) {
printf ( " argc: %d \n " , argc ) ;
printf ( " len: %d \n " , len ) ;
printf ( " start: %d \n " , start ) ;
printf ( " rsize: %d \n " , rsize ) ;
}
if ( r = = - 1 ) {
/* copy post argument */
MEMMOVE ( & argv [ start ] , & argv [ m + osize ] , VALUE , psize ) ;
2007-07-07 11:16:05 +04:00
}
2007-06-25 20:05:17 +04:00
else {
2008-10-27 16:35:46 +03:00
ary = rb_ary_new4 ( rsize , & argv [ r ] ) ;
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
/* copy post argument */
MEMMOVE ( & argv [ start ] , & argv [ m + rsize + osize ] , VALUE , psize ) ;
argv [ r ] = ary ;
}
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
for ( i = psize ; i < len ; i + + ) {
argv [ start + i ] = Qnil ;
}
2007-06-25 20:05:17 +04:00
2009-05-20 13:58:29 +04:00
return ( int ) opt_pc ;
2008-10-27 16:35:46 +03:00
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
static inline int
vm_yield_setup_block_args ( rb_thread_t * th , const rb_iseq_t * iseq ,
2009-07-15 18:59:41 +04:00
int orig_argc , VALUE * argv ,
const rb_block_t * blockptr )
2008-10-27 16:35:46 +03:00
{
int i ;
int argc = orig_argc ;
const int m = iseq - > argc ;
2009-07-05 03:08:32 +04:00
VALUE ary , arg0 ;
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
int opt_pc = 0 ;
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
th - > mark_stack_len = argc ;
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
/*
* yield [ 1 , 2 ]
* = > { | a | } = > a = [ 1 , 2 ]
* = > { | a , b | } = > a , b = [ 1 , 2 ]
*/
2009-07-05 03:08:32 +04:00
arg0 = argv [ 0 ] ;
2008-10-27 16:35:46 +03:00
if ( ! ( iseq - > arg_simple & 0x02 ) & & /* exclude {|a|} */
( m + iseq - > arg_post_len ) > 0 & & /* this process is meaningful */
2009-07-05 03:08:32 +04:00
argc = = 1 & & ! NIL_P ( ary = rb_check_array_type ( arg0 ) ) ) { /* rhs is only an array */
2009-05-20 20:43:41 +04:00
th - > mark_stack_len = argc = RARRAY_LENINT ( ary ) ;
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
CHECK_STACK_OVERFLOW ( th - > cfp , argc ) ;
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
MEMCPY ( argv , RARRAY_PTR ( ary ) , VALUE , argc ) ;
}
2009-07-05 03:08:32 +04:00
else {
argv [ 0 ] = arg0 ;
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
for ( i = argc ; i < m ; i + + ) {
argv [ i ] = Qnil ;
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
if ( iseq - > arg_rest = = - 1 & & iseq - > arg_opts = = 0 ) {
const int arg_size = iseq - > arg_size ;
if ( arg_size < argc ) {
/*
* yield 1 , 2
* = > { | a | } # truncate
*/
th - > mark_stack_len = argc = arg_size ;
}
}
else {
int r = iseq - > arg_rest ;
2007-06-25 20:05:17 +04:00
2009-02-22 17:23:33 +03:00
if ( iseq - > arg_post_len | |
2008-10-27 16:35:46 +03:00
iseq - > arg_opts ) { /* TODO: implement simple version for (iseq->arg_post_len==0 && iseq->arg_opts > 0) */
opt_pc = vm_yield_setup_block_args_complex ( th , iseq , argc , argv ) ;
}
else {
if ( argc < r ) {
/* yield 1
* = > { | a , b , * r | }
*/
for ( i = argc ; i < r ; i + + ) {
argv [ i ] = Qnil ;
}
argv [ r ] = rb_ary_new ( ) ;
}
else {
argv [ r ] = rb_ary_new4 ( argc - r , & argv [ r ] ) ;
}
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
th - > mark_stack_len = iseq - > arg_size ;
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
/* {|&b|} */
if ( iseq - > arg_block ! = - 1 ) {
VALUE procval = Qnil ;
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
if ( blockptr ) {
2009-07-15 18:59:41 +04:00
if ( blockptr - > proc = = 0 ) {
procval = rb_vm_make_proc ( th , blockptr , rb_cProc ) ;
}
else {
procval = blockptr - > proc ;
}
2008-10-27 16:35:46 +03:00
}
2007-06-25 20:05:17 +04:00
2008-10-27 16:35:46 +03:00
argv [ iseq - > arg_block ] = procval ;
}
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
th - > mark_stack_len = 0 ;
return opt_pc ;
}
2007-06-25 06:44:20 +04:00
2008-10-27 16:35:46 +03:00
static inline int
vm_yield_setup_args ( rb_thread_t * const th , const rb_iseq_t * iseq ,
int argc , VALUE * argv ,
const rb_block_t * blockptr , int lambda )
{
if ( 0 ) { /* for debug */
printf ( " argc: %d \n " , argc ) ;
printf ( " iseq argc: %d \n " , iseq - > argc ) ;
printf ( " iseq opts: %d \n " , iseq - > arg_opts ) ;
printf ( " iseq rest: %d \n " , iseq - > arg_rest ) ;
printf ( " iseq post: %d \n " , iseq - > arg_post_len ) ;
printf ( " iseq blck: %d \n " , iseq - > arg_block ) ;
printf ( " iseq smpl: %d \n " , iseq - > arg_simple ) ;
printf ( " lambda: %s \n " , lambda ? " true " : " false " ) ;
}
if ( lambda ) {
/* call as method */
2009-11-07 06:51:39 +03:00
int opt_pc ;
VM_CALLEE_SETUP_ARG ( opt_pc , th , iseq , argc , argv , & blockptr ) ;
2008-10-27 16:35:46 +03:00
return opt_pc ;
}
else {
return vm_yield_setup_block_args ( th , iseq , argc , argv , blockptr ) ;
2007-06-25 06:44:20 +04:00
}
}
2007-08-06 15:36:30 +04:00
static VALUE
2008-05-22 20:19:14 +04:00
vm_invoke_block ( rb_thread_t * th , rb_control_frame_t * reg_cfp , rb_num_t num , rb_num_t flag )
2007-08-06 15:36:30 +04:00
{
2009-07-15 18:59:41 +04:00
const rb_block_t * block = GET_BLOCK_PTR ( ) ;
2007-08-06 15:36:30 +04:00
rb_iseq_t * iseq ;
2009-05-20 13:58:29 +04:00
int argc = ( int ) num ;
2010-05-13 11:19:59 +04:00
VALUE type = GET_ISEQ ( ) - > local_iseq - > type ;
2007-08-06 15:36:30 +04:00
2010-05-09 22:21:39 +04:00
if ( ( type ! = ISEQ_TYPE_METHOD & & type ! = ISEQ_TYPE_CLASS ) | | block = = 0 ) {
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
rb_vm_localjump_error ( " no block given (yield) " , Qnil , 0 ) ;
2007-08-06 15:36:30 +04:00
}
iseq = block - > iseq ;
2007-11-28 10:31:10 +03:00
argc = caller_setup_args ( th , GET_CFP ( ) , flag , argc , 0 , 0 ) ;
2007-08-06 15:36:30 +04:00
if ( BUILTIN_TYPE ( iseq ) ! = T_NODE ) {
int opt_pc ;
2007-12-18 16:14:32 +03:00
const int arg_size = iseq - > arg_size ;
2008-05-21 19:18:15 +04:00
VALUE * const rsp = GET_SP ( ) - argc ;
2007-12-18 16:14:32 +03:00
SET_SP ( rsp ) ;
2007-08-06 15:36:30 +04:00
CHECK_STACK_OVERFLOW ( GET_CFP ( ) , iseq - > stack_max ) ;
2007-12-18 16:14:32 +03:00
opt_pc = vm_yield_setup_args ( th , iseq , argc , rsp , 0 ,
2007-08-06 15:36:30 +04:00
block_proc_is_lambda ( block - > proc ) ) ;
vm_push_frame ( th , iseq ,
* 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
2008-06-11 01:46:43 +04:00
VM_FRAME_MAGIC_BLOCK , block - > self , ( VALUE ) block - > dfp ,
2007-12-18 16:14:32 +03:00
iseq - > iseq_encoded + opt_pc , rsp + arg_size , block - > lfp ,
iseq - > local_size - arg_size ) ;
2007-08-06 15:36:30 +04:00
return Qundef ;
}
else {
2008-06-09 19:52:51 +04:00
VALUE val = vm_yield_with_cfunc ( th , block , block - > self , argc , STACK_ADDR_FROM_TOP ( argc ) , 0 ) ;
2007-11-28 10:31:10 +03:00
POPN ( argc ) ; /* TODO: should put before C/yield? */
2007-08-06 15:36:30 +04:00
return val ;
}
}
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
/* svar */
2007-06-24 21:19:22 +04:00
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
static inline NODE *
2008-05-22 20:19:14 +04:00
lfp_svar_place ( rb_thread_t * th , VALUE * lfp )
2007-06-24 21:19:22 +04: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
2008-06-11 01:46:43 +04:00
VALUE * svar ;
2007-06-24 21:19:22 +04: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
2008-06-11 01:46:43 +04:00
if ( lfp & & th - > local_lfp ! = lfp ) {
svar = & lfp [ - 1 ] ;
2007-06-24 21:19:22 +04:00
}
else {
* 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
2008-06-11 01:46:43 +04:00
svar = & th - > local_svar ;
}
if ( NIL_P ( * svar ) ) {
* svar = ( VALUE ) NEW_IF ( Qnil , Qnil , Qnil ) ;
2007-06-24 21:19:22 +04: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
2008-06-11 01:46:43 +04:00
return ( NODE * ) * svar ;
2007-07-10 12:04:52 +04:00
}
static VALUE
2008-05-22 20:19:14 +04:00
lfp_svar_get ( rb_thread_t * th , VALUE * lfp , VALUE key )
2007-07-10 12:04:52 +04:00
{
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
NODE * svar = lfp_svar_place ( th , lfp ) ;
2007-07-10 12:04:52 +04:00
switch ( key ) {
2007-06-24 21:19:22 +04:00
case 0 :
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
return svar - > u1 . value ;
2007-06-24 21:19:22 +04:00
case 1 :
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
return svar - > u2 . value ;
2007-07-10 12:04:52 +04:00
default : {
2008-05-21 19:18:15 +04:00
const VALUE hash = svar - > u3 . value ;
2007-07-10 12:04:52 +04:00
2007-08-18 09:11:49 +04:00
if ( hash = = Qnil ) {
return Qnil ;
}
else {
return rb_hash_lookup ( hash , key ) ;
}
2007-07-10 12:04:52 +04:00
}
}
}
static void
2008-05-22 20:19:14 +04:00
lfp_svar_set ( rb_thread_t * th , VALUE * lfp , VALUE key , VALUE val )
2007-07-10 12:04:52 +04:00
{
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
NODE * svar = lfp_svar_place ( th , lfp ) ;
2007-07-10 12:04:52 +04:00
switch ( key ) {
case 0 :
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
svar - > u1 . value = val ;
2007-07-10 12:04:52 +04:00
return ;
case 1 :
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
svar - > u2 . value = val ;
2007-07-10 14:22:30 +04:00
return ;
2007-07-10 12:04:52 +04:00
default : {
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
VALUE hash = svar - > u3 . value ;
2007-07-10 12:04:52 +04:00
2007-08-18 09:11:49 +04:00
if ( hash = = Qnil ) {
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
svar - > u3 . value = hash = rb_hash_new ( ) ;
2007-08-18 09:11:49 +04:00
}
rb_hash_aset ( hash , key , val ) ;
2007-06-24 21:19:22 +04:00
}
}
}
2007-08-06 15:36:30 +04:00
static inline VALUE
2008-05-22 20:19:14 +04:00
vm_getspecial ( rb_thread_t * th , VALUE * lfp , VALUE key , rb_num_t type )
2007-08-06 15:36:30 +04:00
{
VALUE val ;
if ( type = = 0 ) {
2008-05-21 19:18:15 +04:00
VALUE k = key ;
if ( FIXNUM_P ( key ) ) {
k = FIX2INT ( key ) ;
}
val = lfp_svar_get ( th , lfp , k ) ;
2007-08-06 15:36:30 +04:00
}
else {
VALUE backref = lfp_svar_get ( th , lfp , 1 ) ;
if ( type & 0x01 ) {
switch ( type > > 1 ) {
case ' & ' :
val = rb_reg_last_match ( backref ) ;
break ;
case ' ` ' :
val = rb_reg_match_pre ( backref ) ;
break ;
case ' \' ' :
val = rb_reg_match_post ( backref ) ;
break ;
case ' + ' :
val = rb_reg_match_last ( backref ) ;
break ;
default :
rb_bug ( " unexpected back-ref " ) ;
}
}
else {
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
val = rb_reg_nth_match ( ( int ) ( type > > 1 ) , backref ) ;
2007-08-06 15:36:30 +04:00
}
}
return val ;
}
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
static NODE *
2008-05-22 20:19:14 +04:00
vm_get_cref ( const rb_iseq_t * iseq , const VALUE * lfp , const VALUE * dfp )
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
{
NODE * cref = 0 ;
while ( 1 ) {
if ( lfp = = dfp ) {
cref = iseq - > cref_stack ;
break ;
}
else if ( dfp [ - 1 ] ! = Qnil ) {
cref = ( NODE * ) dfp [ - 1 ] ;
break ;
}
dfp = GET_PREV_DFP ( dfp ) ;
}
if ( cref = = 0 ) {
rb_bug ( " vm_get_cref: unreachable " ) ;
}
return cref ;
}
* common.mk: clean up
- remove blockinlining.$(OBJEXT) to built
- make ENCODING_H_INCLDUES variable (include/ruby/encoding.h)
- make VM_CORE_H_INCLUDES variable (vm_core.h)
- simplify rules.
- make depends rule to output depend status using gcc -MM.
* include/ruby/mvm.h, include/ruby/vm.h: rename mvm.h to vm.h.
* include/ruby.h: ditto.
* load.c: add inclusion explicitly.
* enumerator.c, object.c, parse.y, thread.c, vm_dump.c:
remove useless inclusion.
* eval_intern.h: cleanup inclusion.
* vm_core.h: rb_thread_t should be defined in this file.
* vm_evalbody.c, vm_exec.c: rename vm_evalbody.c to vm_exec.c.
* vm.h, vm_exec.h: rename vm.h to vm_exec.h.
* insnhelper.h, vm_insnhelper.h: rename insnhelper.h to vm_insnhelper.h.
* vm.c, vm_insnhelper.c, vm_insnhelper.h:
- rename vm_eval() to vm_exec_core().
- rename vm_eval_body() to vm_exec().
- cleanup include order.
* vm_method.c: fix comment.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-23 04:20:28 +04:00
static NODE *
2009-12-03 21:25:57 +03:00
vm_cref_push ( rb_thread_t * th , VALUE klass , int noex , rb_block_t * blockptr )
* common.mk: clean up
- remove blockinlining.$(OBJEXT) to built
- make ENCODING_H_INCLDUES variable (include/ruby/encoding.h)
- make VM_CORE_H_INCLUDES variable (vm_core.h)
- simplify rules.
- make depends rule to output depend status using gcc -MM.
* include/ruby/mvm.h, include/ruby/vm.h: rename mvm.h to vm.h.
* include/ruby.h: ditto.
* load.c: add inclusion explicitly.
* enumerator.c, object.c, parse.y, thread.c, vm_dump.c:
remove useless inclusion.
* eval_intern.h: cleanup inclusion.
* vm_core.h: rb_thread_t should be defined in this file.
* vm_evalbody.c, vm_exec.c: rename vm_evalbody.c to vm_exec.c.
* vm.h, vm_exec.h: rename vm.h to vm_exec.h.
* insnhelper.h, vm_insnhelper.h: rename insnhelper.h to vm_insnhelper.h.
* vm.c, vm_insnhelper.c, vm_insnhelper.h:
- rename vm_eval() to vm_exec_core().
- rename vm_eval_body() to vm_exec().
- cleanup include order.
* vm_method.c: fix comment.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-23 04:20:28 +04:00
{
rb_control_frame_t * cfp = vm_get_ruby_level_caller_cfp ( th , th - > cfp ) ;
2009-08-10 06:40:34 +04:00
NODE * cref = NEW_BLOCK ( klass ) ;
* common.mk: clean up
- remove blockinlining.$(OBJEXT) to built
- make ENCODING_H_INCLDUES variable (include/ruby/encoding.h)
- make VM_CORE_H_INCLUDES variable (vm_core.h)
- simplify rules.
- make depends rule to output depend status using gcc -MM.
* include/ruby/mvm.h, include/ruby/vm.h: rename mvm.h to vm.h.
* include/ruby.h: ditto.
* load.c: add inclusion explicitly.
* enumerator.c, object.c, parse.y, thread.c, vm_dump.c:
remove useless inclusion.
* eval_intern.h: cleanup inclusion.
* vm_core.h: rb_thread_t should be defined in this file.
* vm_evalbody.c, vm_exec.c: rename vm_evalbody.c to vm_exec.c.
* vm.h, vm_exec.h: rename vm.h to vm_exec.h.
* insnhelper.h, vm_insnhelper.h: rename insnhelper.h to vm_insnhelper.h.
* vm.c, vm_insnhelper.c, vm_insnhelper.h:
- rename vm_eval() to vm_exec_core().
- rename vm_eval_body() to vm_exec().
- cleanup include order.
* vm_method.c: fix comment.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-23 04:20:28 +04:00
cref - > nd_file = 0 ;
cref - > nd_visi = noex ;
2009-12-03 21:25:57 +03:00
if ( blockptr ) {
cref - > nd_next = vm_get_cref ( blockptr - > iseq , blockptr - > lfp , blockptr - > dfp ) ;
}
else if ( cfp ) {
2009-08-10 06:40:34 +04:00
cref - > nd_next = vm_get_cref ( cfp - > iseq , cfp - > lfp , cfp - > dfp ) ;
* common.mk: clean up
- remove blockinlining.$(OBJEXT) to built
- make ENCODING_H_INCLDUES variable (include/ruby/encoding.h)
- make VM_CORE_H_INCLUDES variable (vm_core.h)
- simplify rules.
- make depends rule to output depend status using gcc -MM.
* include/ruby/mvm.h, include/ruby/vm.h: rename mvm.h to vm.h.
* include/ruby.h: ditto.
* load.c: add inclusion explicitly.
* enumerator.c, object.c, parse.y, thread.c, vm_dump.c:
remove useless inclusion.
* eval_intern.h: cleanup inclusion.
* vm_core.h: rb_thread_t should be defined in this file.
* vm_evalbody.c, vm_exec.c: rename vm_evalbody.c to vm_exec.c.
* vm.h, vm_exec.h: rename vm.h to vm_exec.h.
* insnhelper.h, vm_insnhelper.h: rename insnhelper.h to vm_insnhelper.h.
* vm.c, vm_insnhelper.c, vm_insnhelper.h:
- rename vm_eval() to vm_exec_core().
- rename vm_eval_body() to vm_exec().
- cleanup include order.
* vm_method.c: fix comment.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-23 04:20:28 +04:00
}
return cref ;
}
static inline VALUE
vm_get_cbase ( const rb_iseq_t * iseq , const VALUE * lfp , const VALUE * dfp )
{
NODE * cref = vm_get_cref ( iseq , lfp , dfp ) ;
VALUE klass = Qundef ;
while ( cref ) {
if ( ( klass = cref - > nd_clss ) ! = 0 ) {
break ;
}
cref = cref - > nd_next ;
}
return klass ;
}
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
2009-12-03 21:25:57 +03:00
static inline VALUE
vm_get_const_base ( const rb_iseq_t * iseq , const VALUE * lfp , const VALUE * dfp )
{
NODE * cref = vm_get_cref ( iseq , lfp , dfp ) ;
VALUE klass = Qundef ;
while ( cref ) {
if ( ! ( cref - > flags & NODE_FL_CREF_PUSHED_BY_EVAL ) & &
( klass = cref - > nd_clss ) ! = 0 ) {
break ;
}
cref = cref - > nd_next ;
}
return klass ;
}
2008-04-03 14:59:44 +04:00
static inline void
2008-05-22 20:19:14 +04:00
vm_check_if_namespace ( VALUE klass )
2008-04-03 14:59:44 +04:00
{
switch ( TYPE ( klass ) ) {
case T_CLASS :
case T_MODULE :
break ;
default :
rb_raise ( rb_eTypeError , " %s is not a class/module " ,
2008-05-05 06:27:29 +04:00
RSTRING_PTR ( rb_inspect ( klass ) ) ) ;
2008-04-03 14:59:44 +04:00
}
}
2007-06-24 21:19:22 +04:00
static inline VALUE
2008-05-22 20:19:14 +04:00
vm_get_ev_const ( rb_thread_t * th , const rb_iseq_t * iseq ,
VALUE orig_klass , ID id , int is_defined )
2007-06-24 21:19:22 +04:00
{
VALUE val ;
2008-05-21 19:18:15 +04:00
if ( orig_klass = = Qnil ) {
2007-06-24 21:19:22 +04:00
/* in current lexical scope */
2009-12-03 21:25:57 +03:00
const NODE * cref = vm_get_cref ( iseq , th - > cfp - > lfp , th - > cfp - > dfp ) ;
const NODE * root_cref = NULL ;
2008-05-21 19:18:15 +04:00
VALUE klass = orig_klass ;
2007-06-24 21:19:22 +04:00
while ( cref & & cref - > nd_next ) {
2009-12-03 21:25:57 +03:00
if ( ! ( cref - > flags & NODE_FL_CREF_PUSHED_BY_EVAL ) ) {
klass = cref - > nd_clss ;
if ( root_cref = = NULL )
root_cref = cref ;
}
2007-06-24 21:19:22 +04:00
cref = cref - > nd_next ;
2008-05-19 22:47:56 +04:00
if ( ! NIL_P ( klass ) ) {
2009-01-31 23:19:44 +03:00
VALUE am = 0 ;
2008-05-19 22:47:56 +04:00
search_continue :
if ( RCLASS_IV_TBL ( klass ) & &
st_lookup ( RCLASS_IV_TBL ( klass ) , id , & val ) ) {
if ( val = = Qundef ) {
2009-01-31 23:19:44 +03:00
if ( am = = klass ) break ;
am = klass ;
2008-05-19 22:47:56 +04:00
rb_autoload_load ( klass , id ) ;
goto search_continue ;
2007-06-24 21:19:22 +04:00
}
else {
2008-05-19 22:47:56 +04:00
if ( is_defined ) {
return 1 ;
}
else {
return val ;
}
2007-06-24 21:19:22 +04:00
}
}
}
}
2008-05-19 22:47:56 +04:00
/* search self */
2009-12-03 21:25:57 +03:00
if ( root_cref & & ! NIL_P ( root_cref - > nd_clss ) ) {
klass = root_cref - > nd_clss ;
}
else {
2008-05-19 22:47:56 +04:00
klass = CLASS_OF ( th - > cfp - > self ) ;
}
2007-06-24 21:19:22 +04:00
if ( is_defined ) {
return rb_const_defined ( klass , id ) ;
}
else {
return rb_const_get ( klass , id ) ;
}
}
else {
2008-05-21 19:18:15 +04:00
vm_check_if_namespace ( orig_klass ) ;
2007-06-24 21:19:22 +04:00
if ( is_defined ) {
2008-05-21 19:18:15 +04:00
return rb_const_defined_from ( orig_klass , id ) ;
2007-06-24 21:19:22 +04:00
}
else {
2008-05-21 19:18:15 +04:00
return rb_const_get_from ( orig_klass , id ) ;
2007-06-24 21:19:22 +04:00
}
}
}
static inline VALUE
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information.
(dfp[-1] points CREF)
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
vm_dump.h, vm_core.h: ditto.
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
changes.
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-05-19 07:08:50 +04:00
vm_get_cvar_base ( NODE * cref )
2007-06-24 21:19:22 +04:00
{
2008-05-19 22:47:56 +04:00
VALUE klass ;
2008-06-17 23:27:24 +04:00
while ( cref & & cref - > nd_next & &
2009-12-03 21:25:57 +03:00
( NIL_P ( cref - > nd_clss ) | | FL_TEST ( cref - > nd_clss , FL_SINGLETON ) | |
( cref - > flags & NODE_FL_CREF_PUSHED_BY_EVAL ) ) ) {
2008-05-19 22:47:56 +04:00
cref = cref - > nd_next ;
2007-06-24 21:19:22 +04:00
if ( ! cref - > nd_next ) {
rb_warn ( " class variable access from toplevel " ) ;
}
}
2008-05-19 22:47:56 +04:00
klass = cref - > nd_clss ;
2007-06-24 21:19:22 +04:00
if ( NIL_P ( klass ) ) {
rb_raise ( rb_eTypeError , " no class variables available " ) ;
}
return klass ;
}
2009-09-06 11:40:24 +04:00
2009-09-07 00:08:00 +04:00
# ifndef USE_IC_FOR_IVAR
# define USE_IC_FOR_IVAR 1
2009-09-06 11:40:24 +04:00
# endif
2009-07-13 08:44:20 +04:00
static VALUE
vm_getivar ( VALUE obj , ID id , IC ic )
{
2009-09-07 00:08:00 +04:00
# if USE_IC_FOR_IVAR
2009-07-13 08:44:20 +04:00
if ( TYPE ( obj ) = = T_OBJECT ) {
VALUE val = Qundef ;
VALUE klass = RBASIC ( obj ) - > klass ;
if ( ic - > ic_class = = klass ) {
2009-09-12 21:16:27 +04:00
long index = ic - > ic_value . index ;
2009-07-13 08:44:20 +04:00
long len = ROBJECT_NUMIV ( obj ) ;
VALUE * ptr = ROBJECT_IVPTR ( obj ) ;
if ( index < len ) {
val = ptr [ index ] ;
}
}
else {
st_data_t index ;
long len = ROBJECT_NUMIV ( obj ) ;
VALUE * ptr = ROBJECT_IVPTR ( obj ) ;
struct st_table * iv_index_tbl = ROBJECT_IV_INDEX_TBL ( obj ) ;
if ( iv_index_tbl ) {
if ( st_lookup ( iv_index_tbl , id , & index ) ) {
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
if ( ( long ) index < len ) {
2009-07-13 08:44:20 +04:00
val = ptr [ index ] ;
}
2009-09-06 11:40:24 +04:00
ic - > ic_class = klass ;
2009-09-12 21:16:27 +04:00
ic - > ic_value . index = index ;
2009-07-13 08:44:20 +04:00
}
}
}
if ( UNLIKELY ( val = = Qundef ) ) {
rb_warning ( " instance variable %s not initialized " , rb_id2name ( id ) ) ;
val = Qnil ;
}
return val ;
}
else {
return rb_ivar_get ( obj , id ) ;
}
# else
return rb_ivar_get ( obj , id ) ;
# endif
}
2009-09-06 11:40:24 +04:00
static void
vm_setivar ( VALUE obj , ID id , VALUE val , IC ic )
{
2009-09-07 00:08:00 +04:00
# if USE_IC_FOR_IVAR
2009-09-06 11:40:24 +04:00
if ( ! OBJ_UNTRUSTED ( obj ) & & rb_safe_level ( ) > = 4 ) {
rb_raise ( rb_eSecurityError , " Insecure: can't modify instance variable " ) ;
}
if ( OBJ_FROZEN ( obj ) ) {
rb_error_frozen ( " object " ) ;
}
if ( TYPE ( obj ) = = T_OBJECT ) {
VALUE klass = RBASIC ( obj ) - > klass ;
st_data_t index ;
if ( ic - > ic_class = = klass ) {
2009-09-12 21:16:27 +04:00
long index = ic - > ic_value . index ;
2009-09-06 11:40:24 +04:00
long len = ROBJECT_NUMIV ( obj ) ;
VALUE * ptr = ROBJECT_IVPTR ( obj ) ;
if ( index < len ) {
ptr [ index ] = val ;
return ; /* inline cache hit */
}
}
else {
struct st_table * iv_index_tbl = ROBJECT_IV_INDEX_TBL ( obj ) ;
if ( iv_index_tbl & & st_lookup ( iv_index_tbl , ( st_data_t ) id , & index ) ) {
ic - > ic_class = klass ;
2009-09-12 21:16:27 +04:00
ic - > ic_value . index = index ;
2009-09-06 11:40:24 +04:00
}
/* fall through */
}
}
rb_ivar_set ( obj , id , val ) ;
# else
rb_ivar_set ( obj , id , val ) ;
# endif
}
2009-07-15 18:59:41 +04:00
static inline const rb_method_entry_t *
2008-05-22 20:19:14 +04:00
vm_method_search ( VALUE id , VALUE klass , IC ic )
2007-06-24 21:19:22 +04:00
{
2009-07-15 18:59:41 +04:00
rb_method_entry_t * me ;
2007-06-24 21:19:22 +04:00
# if OPT_INLINE_METHOD_CACHE
2009-07-15 18:59:41 +04:00
if ( LIKELY ( klass = = ic - > ic_class ) & &
LIKELY ( GET_VM_STATE_VERSION ( ) = = ic - > ic_vmstat ) ) {
2009-09-12 21:16:27 +04:00
me = ic - > ic_value . method ;
2009-07-15 18:59:41 +04:00
}
else {
me = rb_method_entry ( klass , id ) ;
ic - > ic_class = klass ;
2009-09-12 21:16:27 +04:00
ic - > ic_value . method = me ;
2009-07-15 18:59:41 +04:00
ic - > ic_vmstat = GET_VM_STATE_VERSION ( ) ;
2007-06-24 21:19:22 +04:00
}
# else
2009-07-15 18:59:41 +04:00
me = rb_method_entry ( klass , id ) ;
2007-06-24 21:19:22 +04:00
# endif
2009-07-15 18:59:41 +04:00
return me ;
2007-06-24 21:19:22 +04:00
}
2007-08-06 15:36:30 +04:00
static inline VALUE
2008-05-22 20:19:14 +04:00
vm_search_normal_superclass ( VALUE klass , VALUE recv )
2007-06-25 06:44:20 +04:00
{
if ( BUILTIN_TYPE ( klass ) = = T_CLASS ) {
2008-12-25 08:41:47 +03:00
return RCLASS_SUPER ( klass ) ;
2007-06-25 06:44:20 +04:00
}
else if ( BUILTIN_TYPE ( klass ) = = T_MODULE ) {
VALUE k = CLASS_OF ( recv ) ;
while ( k ) {
if ( BUILTIN_TYPE ( k ) = = T_ICLASS & & RBASIC ( k ) - > klass = = klass ) {
2008-12-25 08:41:47 +03:00
return RCLASS_SUPER ( k ) ;
2007-06-25 06:44:20 +04:00
}
2007-09-28 10:21:46 +04:00
k = RCLASS_SUPER ( k ) ;
2007-06-25 06:44:20 +04:00
}
2008-12-25 08:41:47 +03:00
return rb_cObject ;
}
else {
rb_bug ( " vm_search_normal_superclass: should not be reach here " ) ;
2007-06-25 06:44:20 +04:00
}
}
2007-08-06 15:36:30 +04:00
static void
2008-05-22 20:19:14 +04:00
vm_search_superclass ( rb_control_frame_t * reg_cfp , rb_iseq_t * ip ,
VALUE recv , VALUE sigval ,
ID * idp , VALUE * klassp )
2007-08-06 15:36:30 +04:00
{
ID id ;
VALUE klass ;
while ( ip & & ! ip - > klass ) {
ip = ip - > parent_iseq ;
}
if ( ip = = 0 ) {
rb_raise ( rb_eNoMethodError , " super called outside of method " ) ;
}
id = ip - > defined_method_id ;
if ( ip ! = ip - > local_iseq ) {
/* defined by Module#define_method() */
rb_control_frame_t * lcfp = GET_CFP ( ) ;
2009-07-10 05:25:26 +04:00
if ( ! sigval ) {
/* zsuper */
rb_raise ( rb_eRuntimeError , " implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly. " ) ;
}
2007-08-06 15:36:30 +04:00
while ( lcfp - > iseq ! = ip ) {
VALUE * tdfp = GET_PREV_DFP ( lcfp - > dfp ) ;
while ( 1 ) {
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( lcfp ) ;
if ( lcfp - > dfp = = tdfp ) {
break ;
}
}
}
2010-05-27 19:39:34 +04:00
/* temporary measure for [Bug #2420] [Bug #3136] */
if ( ! lcfp - > me ) {
rb_raise ( rb_eNoMethodError , " super called outside of method " ) ;
}
2009-08-28 06:45:41 +04:00
id = lcfp - > me - > def - > original_id ;
2009-07-15 18:59:41 +04:00
klass = vm_search_normal_superclass ( lcfp - > me - > klass , recv ) ;
2007-08-06 15:36:30 +04:00
}
else {
2007-11-22 04:17:52 +03:00
klass = vm_search_normal_superclass ( ip - > klass , recv ) ;
2007-08-06 15:36:30 +04:00
}
* idp = id ;
* klassp = klass ;
}
static VALUE
2008-05-22 20:19:14 +04:00
vm_throw ( rb_thread_t * th , rb_control_frame_t * reg_cfp ,
rb_num_t throw_state , VALUE throwobj )
2007-08-06 15:36:30 +04:00
{
2009-05-20 13:58:29 +04:00
int state = ( int ) ( throw_state & 0xff ) ;
int flag = ( int ) ( throw_state & 0x8000 ) ;
2007-08-06 15:36:30 +04:00
rb_num_t level = throw_state > > 16 ;
if ( state ! = 0 ) {
2008-05-22 08:28:13 +04:00
VALUE * pt = 0 ;
2007-08-06 15:36:30 +04:00
if ( flag ! = 0 ) {
2008-05-24 10:29:48 +04:00
pt = ( void * ) 1 ;
2007-08-06 15:36:30 +04:00
}
else {
if ( state = = TAG_BREAK ) {
rb_control_frame_t * cfp = GET_CFP ( ) ;
VALUE * dfp = GET_DFP ( ) ;
int is_orphan = 1 ;
rb_iseq_t * base_iseq = GET_ISEQ ( ) ;
search_parent :
if ( cfp - > iseq - > type ! = ISEQ_TYPE_BLOCK ) {
2010-05-09 22:21:39 +04:00
if ( cfp - > iseq - > type = = ISEQ_TYPE_CLASS ) {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( cfp ) ;
dfp = cfp - > dfp ;
goto search_parent ;
}
2007-08-06 15:36:30 +04:00
dfp = GC_GUARDED_PTR_REF ( ( VALUE * ) * dfp ) ;
base_iseq = base_iseq - > parent_iseq ;
while ( ( VALUE * ) cfp < th - > stack + th - > stack_size ) {
if ( cfp - > dfp = = dfp ) {
goto search_parent ;
}
2008-06-17 23:27:24 +04:00
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( cfp ) ;
2007-08-06 15:36:30 +04:00
}
rb_bug ( " VM (throw): can't find break base. " ) ;
}
* 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
2008-06-11 01:46:43 +04:00
if ( VM_FRAME_TYPE ( cfp ) = = VM_FRAME_MAGIC_LAMBDA ) {
2007-08-06 15:36:30 +04:00
/* lambda{... break ...} */
is_orphan = 0 ;
2008-06-17 23:27:24 +04:00
pt = cfp - > dfp ;
2008-06-08 15:18:54 +04:00
state = TAG_RETURN ;
2007-08-06 15:36:30 +04:00
}
else {
dfp = GC_GUARDED_PTR_REF ( ( VALUE * ) * dfp ) ;
while ( ( VALUE * ) cfp < th - > stack + th - > stack_size ) {
if ( cfp - > dfp = = dfp ) {
VALUE epc = epc = cfp - > pc - cfp - > iseq - > iseq_encoded ;
rb_iseq_t * iseq = cfp - > iseq ;
int i ;
for ( i = 0 ; i < iseq - > catch_table_size ; i + + ) {
struct iseq_catch_table_entry * entry = & iseq - > catch_table [ i ] ;
if ( entry - > type = = CATCH_TYPE_BREAK & &
entry - > start < epc & & entry - > end > = epc ) {
if ( entry - > cont = = epc ) {
goto found ;
}
else {
break ;
}
}
}
break ;
found :
pt = dfp ;
is_orphan = 0 ;
break ;
}
2008-06-17 23:27:24 +04:00
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( cfp ) ;
2007-08-06 15:36:30 +04:00
}
}
if ( is_orphan ) {
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
rb_vm_localjump_error ( " break from proc-closure " , throwobj , TAG_BREAK ) ;
2007-08-06 15:36:30 +04:00
}
}
else if ( state = = TAG_RETRY ) {
2009-03-12 12:02:06 +03:00
rb_num_t i ;
2007-08-06 15:36:30 +04:00
pt = GC_GUARDED_PTR_REF ( ( VALUE * ) * GET_DFP ( ) ) ;
for ( i = 0 ; i < level ; i + + ) {
pt = GC_GUARDED_PTR_REF ( ( VALUE * ) * pt ) ;
}
}
else if ( state = = TAG_RETURN ) {
rb_control_frame_t * cfp = GET_CFP ( ) ;
VALUE * dfp = GET_DFP ( ) ;
2010-05-09 22:21:39 +04:00
VALUE * lfp = GET_LFP ( ) ;
2007-08-06 15:36:30 +04:00
2008-06-19 06:46:02 +04:00
/* check orphan and get dfp */
2007-08-06 15:36:30 +04:00
while ( ( VALUE * ) cfp < th - > stack + th - > stack_size ) {
2010-05-09 22:21:39 +04:00
if ( ! lfp ) {
lfp = cfp - > lfp ;
}
if ( cfp - > dfp = = lfp & & cfp - > iseq - > type = = ISEQ_TYPE_CLASS ) {
lfp = 0 ;
}
2008-06-19 06:46:02 +04:00
if ( cfp - > lfp = = lfp ) {
* 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
2008-06-11 01:46:43 +04:00
if ( VM_FRAME_TYPE ( cfp ) = = VM_FRAME_MAGIC_LAMBDA ) {
2008-06-19 06:46:02 +04:00
VALUE * tdfp = dfp ;
2008-06-17 23:27:24 +04:00
2008-06-19 06:46:02 +04:00
while ( lfp ! = tdfp ) {
if ( cfp - > dfp = = tdfp ) {
/* in lambda */
dfp = cfp - > dfp ;
goto valid_return ;
}
2010-01-31 15:41:47 +03:00
tdfp = GC_GUARDED_PTR_REF ( ( VALUE * ) * tdfp ) ;
2008-06-19 06:46:02 +04:00
}
2008-06-17 23:27:24 +04:00
}
2008-06-19 06:46:02 +04:00
}
2008-06-17 23:27:24 +04:00
2008-06-19 06:46:02 +04:00
if ( cfp - > dfp = = lfp & & cfp - > iseq - > type = = ISEQ_TYPE_METHOD ) {
dfp = lfp ;
goto valid_return ;
2007-08-06 15:36:30 +04:00
}
2008-06-17 23:27:24 +04:00
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( cfp ) ;
2007-08-06 15:36:30 +04:00
}
* vm.c: add a prefix "rb_" to exposed functions
vm_get_ruby_level_next_cfp(), rb_vm_make_env_object(),
vm_stack_to_heap(), vm_make_proc(), vm_invoke_proc(),
vm_get_sourceline(), vm_cref(), vm_localjump_error(),
vm_make_jump_tag_but_local_jump(), vm_jump_tag_but_local_jump().
This changes may affect only core because most of renamed functions
require a pointer of not-exposed struct such as rb_thread_t or NODE.
In short, they are core functions.
* cont.c, eval.c, eval_intern.h, load.c, proc.c, thread.c,
vm_core.h, vm_dump.c, vm_eval.c, vm_exec.c, vm_insnhelper.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-01-19 05:38:11 +03:00
rb_vm_localjump_error ( " unexpected return " , throwobj , TAG_RETURN ) ;
2007-08-06 15:36:30 +04:00
2008-06-19 06:46:02 +04:00
valid_return :
2008-06-17 23:27:24 +04:00
pt = dfp ;
2007-08-06 15:36:30 +04:00
}
else {
rb_bug ( " isns(throw): unsupport throw type " ) ;
}
}
th - > state = state ;
return ( VALUE ) NEW_THROW_OBJECT ( throwobj , ( VALUE ) pt , state ) ;
}
else {
/* continue throw */
VALUE err = throwobj ;
if ( FIXNUM_P ( err ) ) {
th - > state = FIX2INT ( err ) ;
}
else if ( SYMBOL_P ( err ) ) {
th - > state = TAG_THROW ;
}
else if ( BUILTIN_TYPE ( err ) = = T_NODE ) {
th - > state = GET_THROWOBJ_STATE ( err ) ;
}
else {
2007-08-18 06:48:13 +04:00
th - > state = TAG_RAISE ;
2007-08-23 11:59:42 +04:00
/*th->state = FIX2INT(rb_ivar_get(err, idThrowState));*/
2007-08-06 15:36:30 +04:00
}
return err ;
}
}
2007-08-23 11:10:56 +04:00
static inline void
2009-05-20 13:58:29 +04:00
vm_expandarray ( rb_control_frame_t * cfp , VALUE ary , rb_num_t num , int flag )
2007-08-23 11:10:56 +04:00
{
int is_splat = flag & 0x01 ;
2009-05-20 13:58:29 +04:00
rb_num_t space_size = num + is_splat ;
2007-08-23 11:10:56 +04:00
VALUE * base = cfp - > sp , * ptr ;
2007-09-14 11:26:07 +04:00
volatile VALUE tmp_ary ;
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
rb_num_t len ;
2007-08-23 11:10:56 +04:00
if ( TYPE ( ary ) ! = T_ARRAY ) {
ary = rb_ary_to_ary ( ary ) ;
}
2007-09-14 11:26:07 +04:00
2007-12-20 04:03:15 +03:00
cfp - > sp + = space_size ;
2007-09-14 11:26:07 +04:00
tmp_ary = ary ;
2007-08-23 11:10:56 +04:00
ptr = RARRAY_PTR ( ary ) ;
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
len = ( rb_num_t ) RARRAY_LEN ( ary ) ;
2007-08-23 11:10:56 +04:00
if ( flag & 0x02 ) {
/* post: ..., nil ,ary[-1], ..., ary[0..-num] # top */
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
rb_num_t i = 0 , j ;
2007-08-23 11:10:56 +04:00
if ( len < num ) {
for ( i = 0 ; i < num - len ; i + + ) {
* base + + = Qnil ;
}
}
for ( j = 0 ; i < num ; i + + , j + + ) {
VALUE v = ptr [ len - j - 1 ] ;
* base + + = v ;
}
if ( is_splat ) {
* base = rb_ary_new4 ( len - j , ptr ) ;
}
}
else {
/* normal: ary[num..-1], ary[num-2], ary[num-3], ..., ary[0] # top */
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
rb_num_t i ;
2007-08-23 11:10:56 +04:00
VALUE * bptr = & base [ space_size - 1 ] ;
for ( i = 0 ; i < num ; i + + ) {
if ( len < = i ) {
for ( ; i < num ; i + + ) {
* bptr - - = Qnil ;
}
break ;
}
* bptr - - = ptr [ i ] ;
}
if ( is_splat ) {
if ( num > len ) {
* bptr = rb_ary_new ( ) ;
}
else {
* bptr = rb_ary_new4 ( len - num , ptr + num ) ;
}
}
}
}
2007-12-18 15:07:51 +03:00
static inline int
2009-07-15 18:59:41 +04:00
check_cfunc ( const rb_method_entry_t * me , VALUE ( * func ) ( ) )
2007-12-18 15:07:51 +03:00
{
2009-08-28 06:45:41 +04:00
if ( me & & me - > def - > type = = VM_METHOD_TYPE_CFUNC & &
me - > def - > body . cfunc . func = = func ) {
2007-12-18 15:07:51 +03:00
return 1 ;
}
else {
return 0 ;
}
}
2008-08-08 17:47:48 +04:00
static
# ifndef NO_BIG_INLINE
inline
# endif
VALUE
2008-05-22 20:19:14 +04:00
opt_eq_func ( VALUE recv , VALUE obj , IC ic )
2007-12-18 15:07:51 +03:00
{
if ( FIXNUM_2_P ( recv , obj ) & &
BASIC_OP_UNREDEFINED_P ( BOP_EQ ) ) {
2009-08-15 22:18:07 +04:00
return ( recv = = obj ) ? Qtrue : Qfalse ;
2007-12-18 15:07:51 +03:00
}
else if ( ! SPECIAL_CONST_P ( recv ) & & ! SPECIAL_CONST_P ( obj ) ) {
if ( HEAP_CLASS_OF ( recv ) = = rb_cFloat & &
HEAP_CLASS_OF ( obj ) = = rb_cFloat & &
BASIC_OP_UNREDEFINED_P ( BOP_EQ ) ) {
double a = RFLOAT_VALUE ( recv ) ;
double b = RFLOAT_VALUE ( obj ) ;
if ( isnan ( a ) | | isnan ( b ) ) {
2009-08-15 22:18:07 +04:00
return Qfalse ;
2007-12-18 15:07:51 +03:00
}
2009-08-15 22:18:07 +04:00
return ( a = = b ) ? Qtrue : Qfalse ;
2007-12-18 15:07:51 +03:00
}
else if ( HEAP_CLASS_OF ( recv ) = = rb_cString & &
HEAP_CLASS_OF ( obj ) = = rb_cString & &
BASIC_OP_UNREDEFINED_P ( BOP_EQ ) ) {
2009-08-15 22:18:07 +04:00
return rb_str_equal ( recv , obj ) ;
2007-12-18 15:07:51 +03:00
}
2009-08-15 22:18:07 +04:00
}
2007-12-18 15:07:51 +03:00
2009-08-15 22:18:07 +04:00
{
const rb_method_entry_t * me = vm_method_search ( idEq , CLASS_OF ( recv ) , ic ) ;
extern VALUE rb_obj_equal ( VALUE obj1 , VALUE obj2 ) ;
if ( check_cfunc ( me , rb_obj_equal ) ) {
return recv = = obj ? Qtrue : Qfalse ;
2007-12-18 15:07:51 +03:00
}
}
2009-08-15 22:18:07 +04:00
return Qundef ;
2007-12-18 15:07:51 +03:00
}
2009-08-12 09:55:06 +04:00
struct opt_case_dispatch_i_arg {
VALUE obj ;
int label ;
} ;
static int
2009-11-17 10:26:26 +03:00
opt_case_dispatch_i ( st_data_t key , st_data_t data , st_data_t p )
2009-08-12 09:55:06 +04:00
{
2009-11-17 10:26:26 +03:00
struct opt_case_dispatch_i_arg * arg = ( void * ) p ;
2009-08-13 11:31:23 +04:00
2009-08-12 09:55:06 +04:00
if ( RTEST ( rb_funcall ( ( VALUE ) key , idEqq , 1 , arg - > obj ) ) ) {
arg - > label = FIX2INT ( ( VALUE ) data ) ;
return ST_STOP ;
}
else {
return ST_CONTINUE ;
}
}