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>
2010-10-26 21:27:32 +04:00
# include "constant.h"
2011-05-18 17:41:54 +04:00
# include "internal.h"
2008-01-17 20:06:51 +03:00
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 *
2012-06-11 07:14:59 +04:00
vm_push_frame ( rb_thread_t * th ,
const rb_iseq_t * iseq ,
VALUE type ,
VALUE self ,
2012-08-02 15:08:44 +04:00
VALUE klass ,
2012-06-11 07:14:59 +04:00
VALUE specval ,
const VALUE * pc ,
VALUE * sp ,
2012-07-04 06:11:37 +04:00
int local_size ,
const rb_method_entry_t * me )
2007-06-24 21:19:22 +04:00
{
2012-06-11 07:14:59 +04:00
rb_control_frame_t * const cfp = th - > cfp - 1 ;
2007-06-24 21:19:22 +04:00
int i ;
2012-06-11 07:14:59 +04:00
/* check stack overflow */
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 ;
2012-06-11 07:14:59 +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
/* setup vm value stack */
2009-02-22 17:23:33 +03:00
2012-06-11 07:14:59 +04:00
/* initialize local variables */
2007-06-24 21:19:22 +04:00
for ( i = 0 ; i < local_size ; i + + ) {
2012-06-11 07:14:59 +04:00
* sp + + = Qnil ;
2007-06-24 21:19:22 +04:00
}
/* set special val */
2012-06-11 07:14:59 +04:00
* sp = specval ;
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
/* 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 ;
2012-06-11 07:14:59 +04:00
cfp - > ep = sp ;
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 ;
2010-08-19 01:03:32 +04:00
cfp - > block_iseq = 0 ;
2007-06-24 21:19:22 +04:00
cfp - > proc = 0 ;
2012-07-04 06:11:37 +04:00
cfp - > me = me ;
2012-08-02 15:08:44 +04:00
if ( klass ) {
cfp - > klass = klass ;
}
else {
rb_control_frame_t * prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( cfp ) ;
if ( RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P ( th , prev_cfp ) ) {
cfp - > klass = Qnil ;
}
else {
cfp - > klass = prev_cfp - > klass ;
}
}
2007-06-24 21:19:22 +04:00
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
{
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 */
2012-03-15 01:10:16 +04:00
static inline VALUE
2012-03-15 05:39:00 +04:00
rb_arg_error_new ( int argc , int min , int max )
{
2012-03-15 01:10:16 +04:00
VALUE err_mess = 0 ;
if ( min = = max ) {
err_mess = rb_sprintf ( " wrong number of arguments (%d for %d) " , argc , min ) ;
}
else if ( max = = UNLIMITED_ARGUMENTS ) {
err_mess = rb_sprintf ( " wrong number of arguments (%d for %d+) " , argc , min ) ;
}
else {
err_mess = rb_sprintf ( " wrong number of arguments (%d for %d..%d) " , argc , min , max ) ;
}
return rb_exc_new3 ( rb_eArgError , err_mess ) ;
}
2007-06-24 21:19:22 +04:00
2012-03-15 01:10:16 +04:00
NORETURN ( static void argument_error ( const rb_iseq_t * iseq , int miss_argc , int min_argc , int max_argc ) ) ;
2010-05-04 07:50:39 +04:00
static void
2012-03-15 01:10:16 +04:00
argument_error ( const rb_iseq_t * iseq , int miss_argc , int min_argc , int max_argc )
2010-05-04 07:50:39 +04:00
{
2012-03-15 01:10:16 +04:00
VALUE exc = rb_arg_error_new ( miss_argc , min_argc , max_argc ) ;
2010-05-04 07:50:39 +04:00
VALUE bt = rb_make_backtrace ( ) ;
VALUE err_line = 0 ;
if ( iseq ) {
2012-03-16 07:00:44 +04:00
int line_no = rb_iseq_first_lineno ( iseq ) ;
2010-05-04 07:50:39 +04:00
err_line = rb_sprintf ( " %s:%d:in `%s' " ,
2012-06-04 06:49:37 +04:00
RSTRING_PTR ( iseq - > location . path ) ,
line_no , RSTRING_PTR ( iseq - > location . label ) ) ;
2010-05-04 07:50:39 +04:00
rb_funcall ( bt , rb_intern ( " unshift " ) , 1 , err_line ) ;
}
rb_funcall ( exc , rb_intern ( " set_backtrace " ) , 1 , bt ) ;
rb_exc_raise ( exc ) ;
}
2011-12-26 18:20:09 +04:00
NORETURN ( static void unknown_keyword_error ( const rb_iseq_t * iseq , VALUE hash ) ) ;
static void
unknown_keyword_error ( const rb_iseq_t * iseq , VALUE hash )
{
2011-12-26 18:20:20 +04:00
VALUE sep = rb_usascii_str_new2 ( " , " ) , keys ;
const char * msg ;
int i ;
for ( i = 0 ; i < iseq - > arg_keywords ; i + + ) {
rb_hash_delete ( hash , ID2SYM ( iseq - > arg_keyword_table [ i ] ) ) ;
}
keys = rb_funcall ( hash , rb_intern ( " keys " ) , 0 , 0 ) ;
2012-05-23 11:13:21 +04:00
if ( ! RB_TYPE_P ( keys , T_ARRAY ) ) rb_raise ( rb_eArgError , " unknown keyword " ) ;
2012-05-24 18:36:54 +04:00
msg = RARRAY_LEN ( keys ) = = 1 ? " " : " s " ;
2011-12-26 18:20:20 +04:00
keys = rb_funcall ( keys , rb_intern ( " join " ) , 1 , sep ) ;
2012-05-24 18:36:54 +04:00
rb_raise ( rb_eArgError , " unknown keyword%s: % " PRIsVALUE , msg , keys ) ;
2011-12-26 18:20:09 +04:00
}
2012-03-15 01:10:34 +04:00
void
2012-03-15 05:39:00 +04:00
rb_error_arity ( int argc , int min , int max )
{
2012-03-15 01:10:34 +04:00
rb_exc_raise ( rb_arg_error_new ( argc , min , max ) ) ;
}
2009-11-07 06:51:39 +03:00
# define VM_CALLEE_SETUP_ARG(ret, th, iseq, orig_argc, orig_argv, block) \
2011-01-13 14:49:54 +03:00
if ( LIKELY ( ( iseq ) - > arg_simple & 0x01 ) ) { \
2008-06-06 18:48:07 +04:00
/* simple check */ \
2011-01-13 14:49:54 +03:00
if ( ( orig_argc ) ! = ( iseq ) - > argc ) { \
2012-03-15 01:10:16 +04:00
argument_error ( ( iseq ) , ( orig_argc ) , ( iseq ) - > argc , ( iseq ) - > argc ) ; \
2008-06-06 18:48:07 +04:00
} \
2011-01-13 14:49:54 +03:00
( ret ) = 0 ; \
2008-06-06 18:48:07 +04:00
} \
else { \
2011-01-13 14:49:54 +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 ;
2012-03-15 01:10:16 +04:00
const int opts = iseq - > arg_opts - ( iseq - > arg_opts > 0 ) ;
const int min = m + iseq - > arg_post_len ;
const int max = ( iseq - > arg_rest = = - 1 ) ? m + opts + iseq - > arg_post_len : UNLIMITED_ARGUMENTS ;
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 ;
2011-12-26 18:20:09 +04:00
VALUE keyword_hash = Qnil ;
2007-06-24 21:19:22 +04:00
2008-06-06 18:48:07 +04:00
th - > mark_stack_len = argc + iseq - > arg_size ;
2011-12-26 18:20:09 +04:00
if ( iseq - > arg_keyword ! = - 1 ) {
int i , j ;
2012-03-13 17:00:17 +04:00
if ( argc > 0 ) keyword_hash = rb_check_hash_type ( argv [ argc - 1 ] ) ;
2011-12-26 18:20:09 +04:00
if ( ! NIL_P ( keyword_hash ) ) {
argc - - ;
keyword_hash = rb_hash_dup ( keyword_hash ) ;
2011-12-26 18:20:15 +04:00
if ( iseq - > arg_keyword_check ) {
2011-12-26 18:20:09 +04:00
for ( i = j = 0 ; i < iseq - > arg_keywords ; i + + ) {
if ( st_lookup ( RHASH_TBL ( keyword_hash ) , ID2SYM ( iseq - > arg_keyword_table [ i ] ) , 0 ) ) j + + ;
}
if ( RHASH_TBL ( keyword_hash ) - > num_entries > ( unsigned int ) j ) {
unknown_keyword_error ( iseq , keyword_hash ) ;
}
}
}
else {
keyword_hash = rb_hash_new ( ) ;
}
}
2008-06-06 18:48:07 +04:00
/* mandatory */
2012-03-15 01:10:16 +04:00
if ( ( argc < min ) | | ( argc > max & & max ! = UNLIMITED_ARGUMENTS ) ) {
argument_error ( iseq , argc , min , max ) ;
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 ) {
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
2011-12-26 18:20:09 +04:00
/* keyword argument */
if ( iseq - > arg_keyword ! = - 1 ) {
orig_argv [ iseq - > arg_keyword ] = keyword_hash ;
}
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 ( 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 ;
2010-12-21 00:10:24 +03:00
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); */
2012-03-15 01:10:34 +04:00
if ( len > = 0 ) rb_check_arity ( argc , len , len ) ;
2007-06-24 21:19:22 +04:00
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 ) ;
2012-04-14 04:36:26 +04:00
UNREACHABLE ;
2007-06-24 21:19:22 +04:00
}
}
static inline VALUE
2011-09-20 16:16:08 +04:00
vm_call_cfunc ( rb_thread_t * th , rb_control_frame_t * reg_cfp ,
2011-07-22 16:52:25 +04:00
int num , volatile VALUE recv , const rb_block_t * blockptr ,
2012-08-02 15:08:44 +04:00
const rb_method_entry_t * me , VALUE defined_class )
2007-06-24 21:19:22 +04:00
{
2011-06-22 15:00:24 +04:00
volatile VALUE val = 0 ;
2009-08-28 06:45:41 +04:00
const rb_method_definition_t * def = me - > def ;
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
2012-08-02 15:08:44 +04:00
vm_push_frame ( th , 0 , VM_FRAME_MAGIC_CFUNC , recv , defined_class ,
2012-07-18 12:40:17 +04:00
VM_ENVVAL_BLOCK_PTR ( blockptr ) , 0 , th - > cfp - > sp , 1 , me ) ;
2012-06-11 07:14:59 +04:00
2010-01-24 16:52:32 +03:00
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 ,
2012-08-02 15:08:44 +04:00
const rb_block_t * blockptr , const rb_method_entry_t * me ,
VALUE defined_class )
2007-06-24 21:19:22 +04:00
{
rb_proc_t * proc ;
VALUE val ;
2011-06-30 17:34:53 +04:00
EXEC_EVENT_HOOK ( th , RUBY_EVENT_CALL , recv , me - > called_id , me - > klass ) ;
2007-06-24 21:19:22 +04:00
/* control block frame */
2010-05-05 21:51:21 +04:00
th - > passed_me = me ;
2009-08-28 06:45:41 +04:00
GetProcPtr ( me - > def - > body . proc , proc ) ;
2012-08-20 15:36:34 +04:00
val = vm_invoke_proc ( th , proc , recv , defined_class , argc , argv , blockptr ) ;
2011-06-30 17:34:53 +04:00
EXEC_EVENT_HOOK ( th , RUBY_EVENT_RETURN , recv , me - > called_id , me - > klass ) ;
2007-06-24 21:19:22 +04:00
return val ;
}
2009-02-22 04:43:59 +03:00
static inline VALUE
2012-09-12 17:59:10 +04:00
vm_method_missing ( rb_thread_t * th , rb_control_frame_t * const reg_cfp ,
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
{
2012-09-12 17:59:10 +04:00
VALUE ret , * argv = STACK_ADDR_FROM_TOP ( num + 1 ) ;
th - > method_missing_reason = opt ;
th - > passed_block = blockptr ;
2009-02-22 04:43:59 +03:00
argv [ 0 ] = ID2SYM ( id ) ;
2012-09-12 17:59:10 +04:00
ret = rb_funcall2 ( recv , idMethodMissing , num + 1 , argv ) ;
POPN ( num + 1 ) ;
return ret ;
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 ,
2012-08-02 15:08:44 +04:00
const rb_method_entry_t * me , VALUE defined_class )
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
2012-08-22 10:28:51 +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 ;
}
2012-08-02 15:08:44 +04:00
vm_push_frame ( th , iseq , VM_FRAME_MAGIC_METHOD , recv , defined_class ,
2012-06-11 07:14:59 +04:00
VM_ENVVAL_BLOCK_PTR ( blockptr ) ,
2012-07-04 06:11:37 +04:00
iseq - > iseq_encoded + opt_pc , sp , 0 , me ) ;
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 ;
2012-08-22 10:28:51 +04:00
int is_finish_frame = VM_FRAME_TYPE_FINISH_P ( cfp ) ;
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 ;
}
2012-08-22 10:28:51 +04:00
vm_push_frame ( th , iseq , VM_FRAME_MAGIC_METHOD | ( is_finish_frame ? VM_FRAME_FLAG_FINISH : 0 ) ,
recv , defined_class , VM_ENVVAL_BLOCK_PTR ( blockptr ) ,
2012-07-04 06:11:37 +04:00
iseq - > iseq_encoded + opt_pc , sp , 0 , me ) ;
2007-06-24 21:19:22 +04:00
}
}
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 ,
2012-08-02 15:08:44 +04:00
ID id , const rb_method_entry_t * me ,
VALUE recv , VALUE defined_class )
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 : {
2012-08-02 15:08:44 +04:00
vm_setup_method ( th , cfp , recv , num , blockptr , flag , me ,
2012-08-02 16:52:50 +04:00
defined_class ) ;
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 : {
2012-08-02 15:08:44 +04:00
val = vm_call_cfunc ( th , cfp , num , recv , blockptr , me ,
defined_class ) ;
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 : {
2012-03-15 01:10:34 +04:00
rb_check_arity ( num , 1 , 1 ) ;
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 : {
2012-03-15 01:10:34 +04:00
rb_check_arity ( num , 0 , 0 ) ;
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 ;
2012-01-30 14:08:23 +04:00
th - > passed_block = blockptr ;
2009-09-28 07:09:16 +04:00
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 ;
2012-08-02 15:08:44 +04:00
val = vm_call_bmethod ( th , recv , num , argv , blockptr , me ,
defined_class ) ;
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 ) ;
2012-08-02 15:08:44 +04:00
me = rb_method_entry ( klass , id , & defined_class ) ;
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 ) ;
2011-10-06 11:29:33 +04:00
if ( SYMBOL_P ( sym ) ) {
id = SYM2ID ( sym ) ;
}
else if ( ! ( id = rb_check_id ( & sym ) ) ) {
if ( rb_method_basic_definition_p ( CLASS_OF ( recv ) , idMethodMissing ) ) {
2011-10-06 15:51:55 +04:00
VALUE exc = make_no_method_exception ( rb_eNoMethodError , NULL , recv ,
2011-10-06 11:29:33 +04:00
rb_long2int ( num ) , & TOPN ( i ) ) ;
rb_exc_raise ( exc ) ;
}
id = rb_to_id ( sym ) ;
}
2009-07-26 13:27:45 +04:00
/* shift arguments */
if ( i > 0 ) {
MEMMOVE ( & TOPN ( i ) , & TOPN ( i - 1 ) , VALUE , i ) ;
2009-07-15 18:59:41 +04:00
}
2012-08-02 15:08:44 +04:00
me = rb_method_entry ( CLASS_OF ( recv ) , id , & defined_class ) ;
2009-07-26 13:27:45 +04:00
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 ;
2012-08-20 15:36:34 +04:00
val = rb_vm_invoke_proc ( th , proc , argc , argv , blockptr ) ;
2009-07-26 13:27:45 +04:00
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 ;
}
2012-09-12 17:59:10 +04:00
val = vm_method_missing ( th , cfp , 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-11-16 10:01:44 +03:00
if ( ! rb_obj_is_kind_of ( cfp - > self , defined_class ) ) {
2012-09-12 17:59:10 +04:00
val = vm_method_missing ( th , cfp , id , recv , num , blockptr , NOEX_PROTECTED ) ;
2007-08-26 00:56:51 +04:00
}
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 ) {
2012-09-12 17:59:10 +04:00
rb_control_frame_t * reg_cfp = cfp ;
VALUE * argv = STACK_ADDR_FROM_TOP ( num ) ;
2009-02-22 04:43:59 +03:00
rb_raise_method_missing ( th , num , argv , recv , stat ) ;
2007-08-26 00:56:51 +04:00
}
else {
2012-09-12 17:59:10 +04:00
val = vm_method_missing ( th , cfp , id , recv , num , blockptr , stat ) ;
2007-06-24 21:19:22 +04:00
}
}
2012-07-19 18:19:40 +04:00
RUBY_VM_CHECK_INTS ( th ) ;
2007-06-24 21:19:22 +04:00
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 ) ;
2012-06-11 07:14:59 +04:00
rb_control_frame_t * cfp ;
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 ;
}
2012-06-11 07:14:59 +04:00
cfp = vm_push_frame ( th , ( rb_iseq_t * ) ifunc , VM_FRAME_MAGIC_IFUNC , self ,
2012-08-02 15:08:44 +04:00
0 , VM_ENVVAL_PREV_EP_PTR ( block - > ep ) , 0 ,
th - > cfp - > sp , 1 , 0 ) ;
2007-06-25 06:44:20 +04:00
2010-09-24 18:45:19 +04:00
if ( blockargptr ) {
2012-06-11 07:14:59 +04:00
VM_CF_LEP ( cfp ) [ 0 ] = VM_ENVVAL_BLOCK_PTR ( blockargptr ) ;
2010-09-24 18:45:19 +04:00
}
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|} */
2011-12-13 00:50:09 +04:00
( m + iseq - > arg_opts + 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
{
2012-06-11 07:14:59 +04:00
const rb_block_t * block = VM_CF_BLOCK_PTR ( reg_cfp ) ;
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 ) ) ;
2012-06-11 07:14:59 +04:00
vm_push_frame ( th , iseq , VM_FRAME_MAGIC_BLOCK , block - > self ,
2012-08-02 15:08:44 +04:00
block - > klass ,
2012-06-11 07:14:59 +04:00
VM_ENVVAL_PREV_EP_PTR ( block - > ep ) ,
iseq - > iseq_encoded + opt_pc ,
rsp + arg_size ,
2012-07-04 06:11:37 +04:00
iseq - > local_size - arg_size , 0 ) ;
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 *
2012-06-11 07:14:59 +04:00
lep_svar_place ( rb_thread_t * th , VALUE * lep )
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
2012-06-11 07:14:59 +04:00
if ( lep & & th - > root_lep ! = lep ) {
svar = & lep [ - 1 ] ;
2007-06-24 21:19:22 +04:00
}
else {
2012-06-11 07:14:59 +04:00
svar = & th - > root_svar ;
* 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 ( 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
2012-06-11 07:14:59 +04:00
lep_svar_get ( rb_thread_t * th , VALUE * lep , VALUE key )
2007-07-10 12:04:52 +04:00
{
2012-06-11 07:14:59 +04:00
NODE * svar = lep_svar_place ( th , lep ) ;
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
2012-06-11 07:14:59 +04:00
lep_svar_set ( rb_thread_t * th , VALUE * lep , VALUE key , VALUE val )
2007-07-10 12:04:52 +04:00
{
2012-06-11 07:14:59 +04:00
NODE * svar = lep_svar_place ( th , lep ) ;
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
2012-06-11 07:14:59 +04:00
vm_getspecial ( rb_thread_t * th , VALUE * lep , 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 ) ;
}
2012-06-11 07:14:59 +04:00
val = lep_svar_get ( th , lep , k ) ;
2007-08-06 15:36:30 +04:00
}
else {
2012-06-11 07:14:59 +04:00
VALUE backref = lep_svar_get ( th , lep , 1 ) ;
2007-08-06 15:36:30 +04:00
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 *
2012-06-11 07:14:59 +04:00
vm_get_cref0 ( const rb_iseq_t * iseq , const VALUE * ep )
* 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
{
while ( 1 ) {
2012-06-11 07:14:59 +04:00
if ( VM_EP_LEP_P ( ep ) ) {
2010-09-23 18:09:22 +04:00
if ( ! RUBY_VM_NORMAL_ISEQ_P ( iseq ) ) return NULL ;
2010-09-23 04:01:40 +04:00
return iseq - > cref_stack ;
* 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
}
2012-06-11 07:14:59 +04:00
else if ( ep [ - 1 ] ! = Qnil ) {
return ( NODE * ) ep [ - 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
}
2012-06-11 07:14:59 +04:00
ep = VM_EP_PREV_EP ( ep ) ;
* 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
}
2010-09-23 04:01:40 +04:00
}
2012-08-02 15:34:19 +04:00
NODE *
rb_vm_get_cref ( const rb_iseq_t * iseq , const VALUE * ep )
2010-09-23 04:01:40 +04:00
{
2012-06-11 07:14:59 +04:00
NODE * cref = vm_get_cref0 ( iseq , ep ) ;
* 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
if ( cref = = 0 ) {
2012-08-02 15:34:19 +04:00
rb_bug ( " rb_vm_get_cref: unreachable " ) ;
* 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 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 ) ;
2012-08-02 15:34:19 +04:00
NODE * cref = NEW_CREF ( klass ) ;
cref - > nd_omod = Qnil ;
* 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_visi = noex ;
2009-12-03 21:25:57 +03:00
if ( blockptr ) {
2012-06-11 07:14:59 +04:00
cref - > nd_next = vm_get_cref0 ( blockptr - > iseq , blockptr - > ep ) ;
2009-12-03 21:25:57 +03:00
}
else if ( cfp ) {
2012-06-11 07:14:59 +04:00
cref - > nd_next = vm_get_cref0 ( cfp - > iseq , cfp - > ep ) ;
* 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
}
2012-08-02 15:34:19 +04:00
/* TODO: why cref->nd_next is 1? */
if ( cref - > nd_next & & cref - > nd_next ! = ( void * ) 1 & &
! NIL_P ( cref - > nd_next - > nd_omod ) ) {
COPY_CREF_OMOD ( cref , cref - > nd_next ) ;
}
* 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
2012-06-11 07:14:59 +04:00
vm_get_cbase ( const rb_iseq_t * iseq , const VALUE * ep )
* 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
{
2012-08-02 15:34:19 +04:00
NODE * cref = rb_vm_get_cref ( iseq , ep ) ;
* 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
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
2012-06-11 07:14:59 +04:00
vm_get_const_base ( const rb_iseq_t * iseq , const VALUE * ep )
2009-12-03 21:25:57 +03:00
{
2012-08-02 15:34:19 +04:00
NODE * cref = rb_vm_get_cref ( iseq , ep ) ;
2009-12-03 21:25:57 +03:00
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
{
2011-02-19 16:41:19 +03:00
VALUE str ;
2012-08-02 02:29:26 +04:00
if ( ! RB_TYPE_P ( klass , T_CLASS ) & & ! RB_TYPE_P ( klass , T_MODULE ) ) {
2011-02-19 16:41:19 +03:00
str = rb_inspect ( klass ) ;
2008-04-03 14:59:44 +04:00
rb_raise ( rb_eTypeError , " %s is not a class/module " ,
2011-02-20 10:23:55 +03:00
StringValuePtr ( str ) ) ;
2008-04-03 14:59:44 +04:00
}
}
2012-08-02 15:34:19 +04:00
static inline VALUE
vm_get_iclass ( rb_control_frame_t * cfp , VALUE klass )
{
if ( TYPE ( klass ) = = T_MODULE & &
2012-08-06 09:55:19 +04:00
FL_TEST ( klass , RMODULE_IS_OVERLAID ) & &
2012-08-02 15:34:19 +04:00
TYPE ( cfp - > klass ) = = T_ICLASS & &
RBASIC ( cfp - > klass ) - > klass = = klass ) {
return cfp - > klass ;
}
else {
return klass ;
}
}
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 */
2012-08-02 15:34:19 +04:00
const NODE * root_cref = rb_vm_get_cref ( iseq , th - > cfp - > ep ) ;
2011-03-31 11:52:40 +04:00
const NODE * cref ;
2008-05-21 19:18:15 +04:00
VALUE klass = orig_klass ;
2007-06-24 21:19:22 +04:00
2011-03-31 11:52:40 +04:00
while ( root_cref & & root_cref - > flags & NODE_FL_CREF_PUSHED_BY_EVAL ) {
root_cref = root_cref - > nd_next ;
}
cref = root_cref ;
2007-06-24 21:19:22 +04:00
while ( cref & & cref - > nd_next ) {
2011-03-31 13:07:42 +04:00
if ( cref - > flags & NODE_FL_CREF_PUSHED_BY_EVAL ) {
klass = Qnil ;
}
else {
klass = cref - > nd_clss ;
}
2007-06-24 21:19:22 +04:00
cref = cref - > nd_next ;
2008-05-19 22:47:56 +04:00
if ( ! NIL_P ( klass ) ) {
2011-08-31 12:28:19 +04:00
VALUE av , am = 0 ;
* compile.c (iseq_build_body), error.c (set_syserr, get_syserr),
(syserr_initialize), gc.c (define_final, rb_gc_copy_finalizer),
(run_final), hash.c (rb_hash_aref, rb_hash_lookup2),
(rb_hash_fetch_m, rb_hash_clear, rb_hash_aset, eql_i),
iseq.c (iseq_load, iseq_data_to_ary), marshal.c (r_symlink),
thread.c (rb_thread_local_aref),
variable.c (generic_ivar_remove, ivar_get, rb_const_get_0),
(rb_cvar_get), vm.c (rb_vm_check_redefinition_opt_method),
vm_insnhelper.c (vm_get_ev_const), vm_method.c (remove_method),
ext/iconv/iconv.c (map_charset): use st_data_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-12 18:47:23 +04:00
st_data_t data ;
2008-05-19 22:47:56 +04:00
search_continue :
2010-10-26 21:27:21 +04:00
if ( RCLASS_CONST_TBL ( klass ) & &
st_lookup ( RCLASS_CONST_TBL ( klass ) , id , & data ) ) {
2010-10-26 21:27:32 +04:00
val = ( ( rb_const_entry_t * ) data ) - > value ;
2008-05-19 22:47:56 +04:00
if ( val = = Qundef ) {
2009-01-31 23:19:44 +03:00
if ( am = = klass ) break ;
am = klass ;
2011-03-24 17:06:31 +03:00
if ( is_defined ) return 1 ;
2011-08-31 12:28:19 +04:00
if ( rb_autoloading_value ( klass , id , & av ) ) return av ;
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 ) ) {
2012-08-02 15:34:19 +04:00
klass = vm_get_iclass ( th - > cfp , root_cref - > nd_clss ) ;
2009-12-03 21:25:57 +03:00
}
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 ) {
2011-01-29 05:01:19 +03:00
return rb_const_defined ( klass , id ) ;
2007-06-24 21:19:22 +04:00
}
else {
2011-01-29 05:01:19 +03:00
return rb_const_get ( klass , id ) ;
2007-06-24 21:19:22 +04:00
}
}
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 ) {
2011-01-28 20:57:27 +03:00
return rb_public_const_defined_from ( orig_klass , id ) ;
2007-06-24 21:19:22 +04:00
}
else {
2011-01-28 20:57:27 +03:00
return rb_public_const_get_from ( orig_klass , id ) ;
2007-06-24 21:19:22 +04:00
}
}
}
static inline VALUE
2012-08-02 15:34:19 +04:00
vm_get_cvar_base ( NODE * cref , rb_control_frame_t * cfp )
2007-06-24 21:19:22 +04:00
{
2008-05-19 22:47:56 +04:00
VALUE klass ;
2011-09-20 13:09:00 +04:00
if ( ! cref ) {
rb_bug ( " vm_get_cvar_base: no cref " ) ;
}
while ( 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 ;
2011-09-20 13:09:00 +04:00
}
if ( ! cref - > nd_next ) {
rb_warn ( " class variable access from toplevel " ) ;
2007-06-24 21:19:22 +04:00
}
2008-05-19 22:47:56 +04:00
2012-08-02 15:34:19 +04:00
klass = vm_get_iclass ( cfp , cref - > nd_clss ) ;
2008-05-19 22:47:56 +04:00
2007-06-24 21:19:22 +04:00
if ( NIL_P ( klass ) ) {
rb_raise ( rb_eTypeError , " no class variables available " ) ;
}
return klass ;
}
2011-09-02 09:36:49 +04:00
static VALUE
vm_search_const_defined_class ( const VALUE cbase , ID id )
2011-09-01 12:31:24 +04:00
{
2011-09-02 09:36:49 +04:00
if ( rb_const_defined_at ( cbase , id ) ) return cbase ;
if ( cbase = = rb_cObject ) {
VALUE tmp = RCLASS_SUPER ( cbase ) ;
while ( tmp ) {
if ( rb_const_defined_at ( tmp , id ) ) return tmp ;
tmp = RCLASS_SUPER ( tmp ) ;
}
2011-09-01 12:31:24 +04:00
}
2011-09-02 09:36:49 +04:00
return 0 ;
2011-09-01 12:31:24 +04:00
}
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
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( obj , T_OBJECT ) ) {
2009-07-13 08:44:20 +04:00
VALUE val = Qundef ;
VALUE klass = RBASIC ( obj ) - > klass ;
2011-07-01 03:23:32 +04:00
if ( LIKELY ( ic - > ic_class = = klass & &
ic - > ic_vmstat = = GET_VM_STATE_VERSION ( ) ) ) {
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 ;
2011-07-01 03:23:32 +04:00
ic - > ic_vmstat = GET_VM_STATE_VERSION ( ) ;
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 " ) ;
}
* array.c, gc.c, hash.c, object.c, string.c, struct.c,
transcode.c, variable.c, vm.c, vm_insnhelper.c, vm_method.c:
replace calls to rb_error_frozen() with rb_check_frozen(). a
patch from Run Paint Run Run at [ruby-core:32014]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2010-10-24 12:14:05 +04:00
rb_check_frozen ( obj ) ;
2009-09-06 11:40:24 +04:00
2011-09-29 15:07:45 +04:00
if ( RB_TYPE_P ( obj , T_OBJECT ) ) {
2009-09-06 11:40:24 +04:00
VALUE klass = RBASIC ( obj ) - > klass ;
st_data_t index ;
2011-07-01 03:23:32 +04:00
if ( LIKELY ( ic - > ic_class = = klass & &
ic - > ic_vmstat = = GET_VM_STATE_VERSION ( ) ) ) {
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 ;
2011-07-01 03:23:32 +04:00
ic - > ic_vmstat = GET_VM_STATE_VERSION ( ) ;
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 *
2012-08-02 15:08:44 +04:00
vm_method_search ( VALUE id , VALUE klass , IC ic , VALUE * defined_class_ptr )
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
2011-06-16 18:42:02 +04:00
if ( LIKELY ( klass = = ic - > ic_class & &
GET_VM_STATE_VERSION ( ) = = ic - > ic_vmstat ) ) {
2009-09-12 21:16:27 +04:00
me = ic - > ic_value . method ;
2012-08-02 15:08:44 +04:00
if ( defined_class_ptr )
* defined_class_ptr = ic - > ic_value2 . defined_class ;
2009-07-15 18:59:41 +04:00
}
else {
2012-08-02 15:08:44 +04:00
VALUE defined_class ;
me = rb_method_entry ( klass , id , & defined_class ) ;
if ( defined_class_ptr )
* defined_class_ptr = defined_class ;
2009-07-15 18:59:41 +04:00
ic - > ic_class = klass ;
2009-09-12 21:16:27 +04:00
ic - > ic_value . method = me ;
2012-08-02 15:08:44 +04:00
ic - > ic_value2 . defined_class = defined_class ;
2009-07-15 18:59:41 +04:00
ic - > ic_vmstat = GET_VM_STATE_VERSION ( ) ;
2007-06-24 21:19:22 +04:00
}
# else
2012-08-02 15:08:44 +04:00
me = rb_method_entry ( klass , id , defined_class_ptr ) ;
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
2012-08-03 20:56:08 +04:00
vm_search_normal_superclass ( VALUE klass )
2007-06-25 06:44:20 +04:00
{
2012-08-03 20:56:08 +04:00
klass = RCLASS_ORIGIN ( klass ) ;
return RCLASS_SUPER ( klass ) ;
2007-06-25 06:44:20 +04:00
}
2012-09-25 04:59:29 +04:00
static void
vm_super_outside ( void )
{
rb_raise ( rb_eNoMethodError , " super called outside of method " ) ;
}
2007-08-06 15:36:30 +04:00
static void
2010-10-14 17:19:30 +04:00
vm_search_superclass ( rb_control_frame_t * reg_cfp , rb_iseq_t * iseq ,
2012-08-03 20:56:08 +04:00
VALUE sigval ,
2008-05-22 20:19:14 +04:00
ID * idp , VALUE * klassp )
2007-08-06 15:36:30 +04:00
{
ID id ;
VALUE klass ;
2010-10-14 17:19:30 +04:00
while ( iseq & & ! iseq - > klass ) {
iseq = iseq - > parent_iseq ;
2007-08-06 15:36:30 +04:00
}
2010-10-14 17:19:30 +04:00
if ( iseq = = 0 ) {
2012-09-25 04:59:29 +04:00
vm_super_outside ( ) ;
2007-08-06 15:36:30 +04:00
}
2010-10-14 17:19:30 +04:00
id = iseq - > defined_method_id ;
2007-08-06 15:36:30 +04:00
2010-10-14 17:19:30 +04:00
if ( iseq ! = iseq - > local_iseq ) {
2007-08-06 15:36:30 +04:00
/* 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. " ) ;
}
2010-10-14 17:19:30 +04:00
while ( lcfp - > iseq ! = iseq ) {
2011-06-25 19:05:37 +04:00
rb_thread_t * th = GET_THREAD ( ) ;
2012-06-11 07:14:59 +04:00
VALUE * tep = VM_EP_PREV_EP ( lcfp - > ep ) ;
2007-08-06 15:36:30 +04:00
while ( 1 ) {
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME ( lcfp ) ;
2011-06-25 19:05:37 +04:00
if ( RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P ( th , lcfp ) ) {
2012-09-25 04:59:29 +04:00
vm_super_outside ( ) ;
2011-06-25 19:05:37 +04:00
}
2012-06-11 07:14:59 +04:00
if ( lcfp - > ep = = tep ) {
2007-08-06 15:36:30 +04:00
break ;
}
}
}
2010-05-27 19:39:34 +04:00
/* temporary measure for [Bug #2420] [Bug #3136] */
if ( ! lcfp - > me ) {
2012-09-25 04:59:29 +04:00
vm_super_outside ( ) ;
2010-05-27 19:39:34 +04:00
}
2009-08-28 06:45:41 +04:00
id = lcfp - > me - > def - > original_id ;
2012-08-03 20:56:08 +04:00
klass = vm_search_normal_superclass ( lcfp - > klass ) ;
2007-08-06 15:36:30 +04:00
}
else {
2012-08-03 20:56:08 +04:00
klass = vm_search_normal_superclass ( reg_cfp - > klass ) ;
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 ( ) ;
2012-06-11 07:14:59 +04:00
VALUE * ep = GET_EP ( ) ;
2007-08-06 15:36:30 +04:00
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 ) ;
2012-06-11 07:14:59 +04:00
ep = cfp - > ep ;
2010-05-09 22:21:39 +04:00
goto search_parent ;
}
2012-06-11 07:14:59 +04:00
ep = VM_EP_PREV_EP ( ep ) ;
2007-08-06 15:36:30 +04:00
base_iseq = base_iseq - > parent_iseq ;
while ( ( VALUE * ) cfp < th - > stack + th - > stack_size ) {
2012-06-11 07:14:59 +04:00
if ( cfp - > ep = = ep ) {
2007-08-06 15:36:30 +04:00
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 ;
2012-06-11 07:14:59 +04:00
pt = cfp - > ep ;
2008-06-08 15:18:54 +04:00
state = TAG_RETURN ;
2007-08-06 15:36:30 +04:00
}
else {
2012-06-11 07:14:59 +04:00
ep = VM_EP_PREV_EP ( ep ) ;
2007-08-06 15:36:30 +04:00
while ( ( VALUE * ) cfp < th - > stack + th - > stack_size ) {
2012-06-11 07:14:59 +04:00
if ( cfp - > ep = = ep ) {
2010-11-16 16:32:30 +03:00
VALUE epc = cfp - > pc - cfp - > iseq - > iseq_encoded ;
2007-08-06 15:36:30 +04:00
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 :
2012-06-11 07:14:59 +04:00
pt = ep ;
2007-08-06 15:36:30 +04:00
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 ;
2012-06-11 07:14:59 +04:00
pt = VM_EP_PREV_EP ( GET_EP ( ) ) ;
2007-08-06 15:36:30 +04:00
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 ( ) ;
2012-06-11 07:14:59 +04:00
VALUE * ep = GET_EP ( ) ;
VALUE * target_lep = VM_CF_LEP ( cfp ) ;
2011-07-10 13:04:44 +04:00
int in_class_frame = 0 ;
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 ) {
2012-06-11 07:14:59 +04:00
VALUE * lep = VM_CF_LEP ( cfp ) ;
if ( ! target_lep ) {
target_lep = lep ;
2010-05-09 22:21:39 +04:00
}
2012-06-11 07:14:59 +04:00
if ( lep = = target_lep & & cfp - > iseq - > type = = ISEQ_TYPE_CLASS ) {
2011-07-10 13:04:44 +04:00
in_class_frame = 1 ;
2012-06-11 07:14:59 +04:00
target_lep = 0 ;
2010-05-09 22:21:39 +04:00
}
2012-06-11 07:14:59 +04:00
if ( lep = = target_lep ) {
* 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 ) {
2012-06-11 07:14:59 +04:00
VALUE * tep = ep ;
2008-06-17 23:27:24 +04:00
2011-07-10 13:04:44 +04:00
if ( in_class_frame ) {
/* lambda {class A; ... return ...; end} */
2012-06-11 07:14:59 +04:00
ep = cfp - > ep ;
2011-07-10 13:04:44 +04:00
goto valid_return ;
}
2012-06-11 07:14:59 +04:00
while ( target_lep ! = tep ) {
if ( cfp - > ep = = tep ) {
2008-06-19 06:46:02 +04:00
/* in lambda */
2012-06-11 07:14:59 +04:00
ep = cfp - > ep ;
2008-06-19 06:46:02 +04:00
goto valid_return ;
}
2012-06-11 07:14:59 +04:00
tep = VM_EP_PREV_EP ( tep ) ;
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
2012-06-11 07:14:59 +04:00
if ( cfp - > ep = = target_lep & & cfp - > iseq - > type = = ISEQ_TYPE_METHOD ) {
ep = target_lep ;
2008-06-19 06:46:02 +04:00
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 :
2012-06-11 07:14:59 +04:00
pt = ep ;
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 ;
* 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
2011-09-29 15:07:45 +04:00
if ( ! RB_TYPE_P ( ary , T_ARRAY ) ) {
2007-08-23 11:10:56 +04:00
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-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 ) ;
}
}
}
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 13:57:00 +04:00
RB_GC_GUARD ( ary ) ;
2007-08-23 11:10:56 +04:00
}
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 ) & &
2011-08-25 02:02:03 +04:00
BASIC_OP_UNREDEFINED_P ( BOP_EQ , FIXNUM_REDEFINED_OP_FLAG ) ) {
2009-08-15 22:18:07 +04:00
return ( recv = = obj ) ? Qtrue : Qfalse ;
2007-12-18 15:07:51 +03:00
}
2012-08-23 11:22:40 +04:00
else if ( FLONUM_2_P ( recv , obj ) & &
BASIC_OP_UNREDEFINED_P ( BOP_EQ , FLOAT_REDEFINED_OP_FLAG ) ) {
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 & &
2012-08-23 11:22:40 +04:00
BASIC_OP_UNREDEFINED_P ( BOP_EQ , FLOAT_REDEFINED_OP_FLAG ) ) {
2007-12-18 15:07:51 +03:00
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 & &
2011-08-25 02:02:03 +04:00
BASIC_OP_UNREDEFINED_P ( BOP_EQ , STRING_REDEFINED_OP_FLAG ) ) {
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
{
2012-08-02 15:08:44 +04:00
const rb_method_entry_t * me = vm_method_search ( idEq , CLASS_OF ( recv ) , ic , 0 ) ;
2009-08-15 22:18:07 +04:00
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
2012-08-02 15:34:19 +04:00
void rb_using_module ( NODE * cref , VALUE module ) ;
static int
vm_using_module_i ( VALUE module , VALUE value , VALUE arg )
{
NODE * cref = ( NODE * ) arg ;
rb_using_module ( cref , module ) ;
return ST_CONTINUE ;
}
static void
rb_vm_using_modules ( NODE * cref , VALUE klass )
{
ID id_using_modules ;
VALUE using_modules ;
CONST_ID ( id_using_modules , " __using_modules__ " ) ;
using_modules = rb_attr_get ( klass , id_using_modules ) ;
switch ( TYPE ( klass ) ) {
case T_CLASS :
if ( NIL_P ( using_modules ) ) {
VALUE super = rb_class_real ( RCLASS_SUPER ( klass ) ) ;
using_modules = rb_attr_get ( super , id_using_modules ) ;
if ( ! NIL_P ( using_modules ) ) {
using_modules = rb_hash_dup ( using_modules ) ;
rb_ivar_set ( klass , id_using_modules , using_modules ) ;
}
}
break ;
case T_MODULE :
rb_using_module ( cref , klass ) ;
break ;
}
if ( ! NIL_P ( using_modules ) ) {
rb_hash_foreach ( using_modules , vm_using_module_i ,
2012-08-02 17:57:19 +04:00
( VALUE ) cref ) ;
2012-08-02 15:34:19 +04:00
}
}
2012-08-08 11:52:19 +04:00
static VALUE
check_match ( VALUE pattern , VALUE target , enum vm_check_match_type type )
{
switch ( type ) {
case VM_CHECKMATCH_TYPE_WHEN :
return pattern ;
case VM_CHECKMATCH_TYPE_CASE :
return rb_funcall2 ( pattern , idEqq , 1 , & target ) ;
case VM_CHECKMATCH_TYPE_RESCUE : {
2012-08-26 11:53:21 +04:00
if ( ! rb_obj_is_kind_of ( pattern , rb_cModule ) ) {
rb_raise ( rb_eTypeError , " class or module required for rescue clause " ) ;
}
return RTEST ( rb_funcall2 ( pattern , idEqq , 1 , & target ) ) ;
2012-08-08 11:52:19 +04:00
}
default :
rb_bug ( " check_match: unreachable " ) ;
}
}
2012-08-23 11:22:40 +04:00
# if defined(_MSC_VER) && _MSC_VER < 1300
# define CHECK_CMP_NAN(a, b) if (isnan(a) || isnan(b)) return Qfalse;
# else
2012-08-23 11:45:46 +04:00
# define CHECK_CMP_NAN(a, b) /* do nothing */
2012-08-23 11:22:40 +04:00
# endif
static inline VALUE
double_cmp_lt ( double a , double b )
{
CHECK_CMP_NAN ( a , b ) ;
return a < b ? Qtrue : Qfalse ;
}
static inline VALUE
double_cmp_le ( double a , double b )
{
CHECK_CMP_NAN ( a , b ) ;
return a < = b ? Qtrue : Qfalse ;
}
static inline VALUE
double_cmp_gt ( double a , double b )
{
CHECK_CMP_NAN ( a , b ) ;
return a > b ? Qtrue : Qfalse ;
}
static inline VALUE
double_cmp_ge ( double a , double b )
{
CHECK_CMP_NAN ( a , b ) ;
return a > = b ? Qtrue : Qfalse ;
}