mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			1699 lines
		
	
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1699 lines
		
	
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** ##skip -*- mode:c; style:ruby; coding: utf-8 -*-
 | 
						||
  insns.def - YARV instruction definitions
 | 
						||
 | 
						||
  $Author: $
 | 
						||
  created at: 04/01/01 01:17:55 JST
 | 
						||
 | 
						||
  Copyright (C) 2004-2007 Koichi Sasada
 | 
						||
*/
 | 
						||
 | 
						||
/** ##skip
 | 
						||
  instruction comment
 | 
						||
  @c: category
 | 
						||
  @e: english description
 | 
						||
  @j: japanese description
 | 
						||
 | 
						||
  instruction form:
 | 
						||
    DEFINE_INSN
 | 
						||
    instruction_name
 | 
						||
    (instruction_operands, ..)
 | 
						||
    (pop_values, ..)
 | 
						||
    (return value)
 | 
						||
    {
 | 
						||
       .. // insn body
 | 
						||
    }
 | 
						||
 | 
						||
 */
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
  @c nop
 | 
						||
  @e nop
 | 
						||
  @j nop
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
nop
 | 
						||
()
 | 
						||
()
 | 
						||
()
 | 
						||
{
 | 
						||
    /* none */
 | 
						||
}
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with variables                                    */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Get local variable (pointed by `idx' and `level').
 | 
						||
     'level' indicates the nesting depth from the current block.
 | 
						||
  @j level, idx で指定されたローカル変数の値をスタックに置く。
 | 
						||
     level はブロックのネストレベルで、何段上かを示す。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getlocal
 | 
						||
(lindex_t idx, rb_num_t level)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = *(vm_get_ep(GET_EP(), level) - idx);
 | 
						||
    RB_DEBUG_COUNTER_INC(lvar_get);
 | 
						||
    (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Set a local variable (pointed to by 'idx') as val.
 | 
						||
     'level' indicates the nesting depth from the current block.
 | 
						||
  @j level, idx で指定されたローカル変数の値を val にする。
 | 
						||
     level はブロックのネストレベルで、何段上かを示す。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setlocal
 | 
						||
(lindex_t idx, rb_num_t level)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    vm_env_write(vm_get_ep(GET_EP(), level), -(int)idx, val);
 | 
						||
    RB_DEBUG_COUNTER_INC(lvar_set);
 | 
						||
    (void)RB_DEBUG_COUNTER_INC_IF(lvar_set_dynamic, level > 0);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Get a block parameter.
 | 
						||
  @j ブロックパラメータを取得する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getblockparam
 | 
						||
(lindex_t idx, rb_num_t level)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    const VALUE *ep = vm_get_ep(GET_EP(), level);
 | 
						||
    VM_ASSERT(VM_ENV_LOCAL_P(ep));
 | 
						||
 | 
						||
    if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) {
 | 
						||
	val = rb_vm_bh_to_procval(ec, VM_ENV_BLOCK_HANDLER(ep));
 | 
						||
	vm_env_write(ep, -(int)idx, val);
 | 
						||
	VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
 | 
						||
    }
 | 
						||
    else {
 | 
						||
	val = *(ep - idx);
 | 
						||
	RB_DEBUG_COUNTER_INC(lvar_get);
 | 
						||
	(void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Set block parameter.
 | 
						||
  @j ブロックパラメータを設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setblockparam
 | 
						||
(lindex_t idx, rb_num_t level)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    const VALUE *ep = vm_get_ep(GET_EP(), level);
 | 
						||
    VM_ASSERT(VM_ENV_LOCAL_P(ep));
 | 
						||
 | 
						||
    vm_env_write(ep, -(int)idx, val);
 | 
						||
    RB_DEBUG_COUNTER_INC(lvar_set);
 | 
						||
    (void)RB_DEBUG_COUNTER_INC_IF(lvar_set_dynamic, level > 0);
 | 
						||
 | 
						||
    VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Get value of special local variable ($~, $_, ..).
 | 
						||
  @j 特殊なローカル変数($~, $_, ...)の値を得る。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getspecial
 | 
						||
(rb_num_t key, rb_num_t type)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_getspecial(ec, GET_LEP(), key, type);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Set value of special local variable ($~, $_, ...) to obj.
 | 
						||
  @j 特別なローカル変数($~, $_, ...)の値を設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setspecial
 | 
						||
(rb_num_t key)
 | 
						||
(VALUE obj)
 | 
						||
()
 | 
						||
{
 | 
						||
    lep_svar_set(ec, GET_LEP(), key, obj);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Get value of instance variable id of self.
 | 
						||
  @j self のインスタンス変数 id の値を得る。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getinstancevariable
 | 
						||
(ID id, IC ic)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_getinstancevariable(GET_SELF(), id, ic);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Set value of instance variable id of self to val.
 | 
						||
  @j self のインスタンス変数 id を val にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setinstancevariable
 | 
						||
(ID id, IC ic)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    vm_setinstancevariable(GET_SELF(), id, val, ic);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Get value of class variable id of klass as val.
 | 
						||
  @j 現在のスコープのクラス変数 id の値を得る。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getclassvariable
 | 
						||
(ID id)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = rb_cvar_get(vm_get_cvar_base(rb_vm_get_cref(GET_EP()), GET_CFP()), id);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e Set value of class variable id of klass as val.
 | 
						||
  @j klass のクラス変数 id を val にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setclassvariable
 | 
						||
(ID id)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    vm_ensure_not_refinement_module(GET_SELF());
 | 
						||
    rb_cvar_set(vm_get_cvar_base(rb_vm_get_cref(GET_EP()), GET_CFP()), id, val);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e
 | 
						||
   Get constant variable id. If klass is Qnil, constants
 | 
						||
   are searched in the current scope. If klass is Qfalse, constants
 | 
						||
   are searched as top level constants. Otherwise, get constant under klass
 | 
						||
   class or module.
 | 
						||
  @j 定数 id の値を得る。
 | 
						||
   klass が Qnil なら、そのスコープで得られる定数の値を得る。
 | 
						||
   Qfalse なら、トップレベルスコープを得る。
 | 
						||
   それ以外なら、klass クラスの下の定数を得る。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getconstant
 | 
						||
(ID id)
 | 
						||
(VALUE klass)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_get_ev_const(ec, klass, id, 0);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e
 | 
						||
   Set constant variable id. If klass is Qfalse, constant
 | 
						||
   is able to access in this scope. if klass is Qnil, set
 | 
						||
   top level constant. otherwise, set constant under klass
 | 
						||
   class or module.
 | 
						||
 | 
						||
  @j 定数 id の値を val にする。
 | 
						||
   klass が Qfalse なら、そのスコープで得られる定数 id の値を設定する。
 | 
						||
   Qnil なら、トップレベルスコープの値を設定する。
 | 
						||
   それ以外なら、klass クラスの下の定数を設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setconstant
 | 
						||
(ID id)
 | 
						||
(VALUE val, VALUE cbase)
 | 
						||
()
 | 
						||
{
 | 
						||
    vm_check_if_namespace(cbase);
 | 
						||
    vm_ensure_not_refinement_module(GET_SELF());
 | 
						||
    rb_const_set(cbase, id, val);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e get global variable id.
 | 
						||
  @j グローバル変数 id の値を得る。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getglobal
 | 
						||
(GENTRY entry)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = GET_GLOBAL((VALUE)entry);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c variable
 | 
						||
  @e set global variable id as val.
 | 
						||
  @j グローバル変数 id の値を設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setglobal
 | 
						||
(GENTRY entry)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    SET_GLOBAL((VALUE)entry, val);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with values                                       */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put nil to stack.
 | 
						||
  @j スタックに nil をプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putnil
 | 
						||
()
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = Qnil;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put self.
 | 
						||
  @j スタックに self をプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putself
 | 
						||
()
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = GET_SELF();
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put some object.
 | 
						||
     i.e. Fixnum, true, false, nil, and so on.
 | 
						||
  @j オブジェクト val をスタックにプッシュする。
 | 
						||
     i.e. Fixnum, true, false, nil, and so on.
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putobject
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    /* */
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put special object.  "value_type" is for expansion.
 | 
						||
  @j 特別なオブジェクト val をスタックにプッシュする。
 | 
						||
     オブジェクトの種類は value_type による.
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putspecialobject
 | 
						||
(rb_num_t value_type)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    enum vm_special_object_type type;
 | 
						||
 | 
						||
    type = (enum vm_special_object_type)value_type;
 | 
						||
    val = vm_get_special_object(GET_EP(), type);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put iseq value.
 | 
						||
  @j iseq をスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putiseq
 | 
						||
(ISEQ iseq)
 | 
						||
()
 | 
						||
(VALUE ret)
 | 
						||
{
 | 
						||
    ret = (VALUE)iseq;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put string val. string will be copied.
 | 
						||
  @j 文字列をコピーしてスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
putstring
 | 
						||
(VALUE str)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = rb_str_resurrect(str);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put concatenate strings
 | 
						||
  @j スタックトップの文字列を n 個連結し,結果をスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
concatstrings
 | 
						||
(rb_num_t num)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - num;
 | 
						||
{
 | 
						||
    val = rb_str_concat_literals(num, STACK_ADDR_FROM_TOP(num));
 | 
						||
    POPN(num);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e push the result of to_s.
 | 
						||
  @j to_s の結果をスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
tostring
 | 
						||
()
 | 
						||
(VALUE val, VALUE str)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
 | 
						||
    val = rb_obj_as_string_result(str, val);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e Freeze (dynamically) created strings. if debug_info is given, set it.
 | 
						||
  @j (埋め込み)文字列を freeze する。もし、debug_info が与えられていれば、それを設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
freezestring
 | 
						||
(VALUE debug_info)
 | 
						||
(VALUE str)
 | 
						||
(VALUE str)
 | 
						||
{
 | 
						||
    vm_freezestring(str, debug_info);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e compile str to Regexp and push it.
 | 
						||
     opt is the option for the Regexp.
 | 
						||
  @j 文字列 str を正規表現にコンパイルしてスタックにプッシュする。
 | 
						||
     コンパイル時,opt を正規表現のオプションとする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
toregexp
 | 
						||
(rb_num_t opt, rb_num_t cnt)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - cnt;
 | 
						||
{
 | 
						||
    VALUE rb_reg_new_ary(VALUE ary, int options);
 | 
						||
    VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *);
 | 
						||
    const VALUE ary = rb_ary_tmp_new_from_values(0, cnt, STACK_ADDR_FROM_TOP(cnt));
 | 
						||
    POPN(cnt);
 | 
						||
    val = rb_reg_new_ary(ary, (int)opt);
 | 
						||
    rb_ary_clear(ary);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e intern str to Symbol and push it.
 | 
						||
  @j 文字列 str をシンボルに変換してスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
intern
 | 
						||
()
 | 
						||
(VALUE str)
 | 
						||
(VALUE sym)
 | 
						||
{
 | 
						||
    sym = rb_str_intern(str);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put new array initialized with num values on the stack.
 | 
						||
  @j 新しい配列をスタック上の num 個の値で初期化して生成しプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
newarray
 | 
						||
(rb_num_t num)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - num;
 | 
						||
{
 | 
						||
    val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
 | 
						||
    POPN(num);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e dup array
 | 
						||
  @j 配列 ary を dup してスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
duparray
 | 
						||
(VALUE ary)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = rb_ary_resurrect(ary);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e if TOS is an array expand, expand it to num objects.
 | 
						||
     if the number of the array is less than num, push nils to fill.
 | 
						||
     if it is greater than num, exceeding elements are dropped.
 | 
						||
     unless TOS is an array, push num - 1 nils.
 | 
						||
     if flags is non-zero, push the array of the rest elements.
 | 
						||
     flag: 0x01 - rest args array
 | 
						||
     flag: 0x02 - for postarg
 | 
						||
     flag: 0x04 - reverse?
 | 
						||
  @j スタックトップのオブジェクトが配列であれば、それを展開する。
 | 
						||
     配列オブジェクトの要素数が num以下ならば、代わりに nil を積む。num以上なら、
 | 
						||
     num以上の要素は切り捨てる。
 | 
						||
     配列オブジェクトでなければ、num - 1 個の nil を積む。
 | 
						||
     もし flag が真なら、残り要素の配列を積む
 | 
						||
     flag: 0x01 - 最後を配列に
 | 
						||
     flag: 0x02 - postarg 用
 | 
						||
     flag: 0x04 - reverse?
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
expandarray
 | 
						||
(rb_num_t num, rb_num_t flag)
 | 
						||
(..., VALUE ary)
 | 
						||
(...) // inc += num - 1 + (flag & 1 ? 1 : 0);
 | 
						||
{
 | 
						||
    vm_expandarray(GET_CFP(), ary, num, (int)flag);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e concat two arrays
 | 
						||
  @j 二つの配列 ary1, ary2 を連結しスタックへプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
concatarray
 | 
						||
()
 | 
						||
(VALUE ary1, VALUE ary2)
 | 
						||
(VALUE ary)
 | 
						||
{
 | 
						||
    ary = vm_concat_array(ary1, ary2);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e call to_a on array ary to splat
 | 
						||
  @j splat のために配列 ary に対して to_a を呼び出す。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
splatarray
 | 
						||
(VALUE flag)
 | 
						||
(VALUE ary)
 | 
						||
(VALUE obj)
 | 
						||
{
 | 
						||
    obj = vm_splat_array(flag, ary);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put new Hash from n elements. n must be an even number.
 | 
						||
  @j 新しいハッシュをスタックトップの n 個を初期値として生成する。
 | 
						||
     n はキーと値のペアなので 2 の倍数でなければならない。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
newhash
 | 
						||
(rb_num_t num)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - num;
 | 
						||
{
 | 
						||
    RUBY_DTRACE_CREATE_HOOK(HASH, num);
 | 
						||
 | 
						||
    val = rb_hash_new_with_size(num / 2);
 | 
						||
 | 
						||
    if (num) {
 | 
						||
        rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
 | 
						||
    }
 | 
						||
    POPN(num);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c put
 | 
						||
  @e put new Range object.(Range.new(low, high, flag))
 | 
						||
  @j Range.new(low, high, flag) のようなオブジェクトを生成しスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
newrange
 | 
						||
(rb_num_t flag)
 | 
						||
(VALUE low, VALUE high)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = rb_range_new(low, high, (int)flag);
 | 
						||
}
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with stack operation                              */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e pop from stack.
 | 
						||
  @j スタックから一つポップする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
pop
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    (void)val;
 | 
						||
    /* none */
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e duplicate stack top.
 | 
						||
  @j スタックトップをコピーしてスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
dup
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
(VALUE val1, VALUE val2)
 | 
						||
{
 | 
						||
    val1 = val2 = val;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e duplicate stack top n elements
 | 
						||
  @j スタックトップの n 個をコピーしてスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
dupn
 | 
						||
(rb_num_t n)
 | 
						||
(...)
 | 
						||
(...) // inc += n;
 | 
						||
{
 | 
						||
    void *dst = GET_SP();
 | 
						||
    void *src = STACK_ADDR_FROM_TOP(n);
 | 
						||
 | 
						||
    INC_SP(n); /* alloca */
 | 
						||
    MEMCPY(dst, src, VALUE, n);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e swap top 2 vals
 | 
						||
  @j スタックトップの 2 つの値を交換する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
swap
 | 
						||
()
 | 
						||
(VALUE val, VALUE obj)
 | 
						||
(VALUE obj, VALUE val)
 | 
						||
{
 | 
						||
    /* none */
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e reverse stack top N order.
 | 
						||
  @j スタックトップの n 個の値を逆転する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
reverse
 | 
						||
(rb_num_t n)
 | 
						||
(...)
 | 
						||
(...) // inc += 0;
 | 
						||
{
 | 
						||
    rb_num_t i;
 | 
						||
    VALUE *sp = STACK_ADDR_FROM_TOP(n);
 | 
						||
 | 
						||
    for (i=0; i<n/2; i++) {
 | 
						||
	VALUE v0 = sp[i];
 | 
						||
	VALUE v1 = TOPN(i);
 | 
						||
	sp[i] = v1;
 | 
						||
	TOPN(i) = v0;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e for stack caching.
 | 
						||
  @j スタックキャッシングの状態を調整するために必要な命令。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
reput
 | 
						||
()
 | 
						||
(..., VALUE val)
 | 
						||
(VALUE val) // inc += 0;
 | 
						||
{
 | 
						||
    /* none */
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e get nth stack value from stack top
 | 
						||
  @j スタックトップから n 個目をスタックにプッシュする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
topn
 | 
						||
(rb_num_t n)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1;
 | 
						||
{
 | 
						||
    val = TOPN(n);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e set Nth stack entry to stack top
 | 
						||
  @j スタックトップの値を n 個目のスタックにコピー
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setn
 | 
						||
(rb_num_t n)
 | 
						||
(..., VALUE val)
 | 
						||
(VALUE val) // inc += 0
 | 
						||
{
 | 
						||
    TOPN(n-1) = val;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c stack
 | 
						||
  @e empty current stack
 | 
						||
  @j current stack を空にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
adjuststack
 | 
						||
(rb_num_t n)
 | 
						||
(...)
 | 
						||
(...) // inc -= n
 | 
						||
{
 | 
						||
    DEC_SP(n);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with setting                                      */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c setting
 | 
						||
  @e defined?
 | 
						||
  @j defined? を行う。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
defined
 | 
						||
(rb_num_t op_type, VALUE obj, VALUE needstr)
 | 
						||
(VALUE v)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_defined(ec, GET_CFP(), op_type, obj, needstr, v);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c setting
 | 
						||
  @e check `target' matches `pattern'.
 | 
						||
     `flag & VM_CHECKMATCH_TYPE_MASK' describe how to check pattern.
 | 
						||
      VM_CHECKMATCH_TYPE_WHEN: ignore target and check pattern is truthy.
 | 
						||
      VM_CHECKMATCH_TYPE_CASE: check `patten === target'.
 | 
						||
      VM_CHECKMATCH_TYPE_RESCUE: check `pattern.kind_op?(Module) && pattern == target'.
 | 
						||
     if `flag & VM_CHECKMATCH_ARRAY' is not 0, then `patten' is array of patterns.
 | 
						||
  @j see above comments.
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
checkmatch
 | 
						||
(rb_num_t flag)
 | 
						||
(VALUE target, VALUE pattern)
 | 
						||
(VALUE result)
 | 
						||
{
 | 
						||
    result = vm_check_match(ec, target, pattern, flag);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c setting
 | 
						||
  @e check keywords are specified or not.
 | 
						||
  @j キーワードが指定されているかどうかチェックする
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
checkkeyword
 | 
						||
(lindex_t kw_bits_index, rb_num_t keyword_index)
 | 
						||
()
 | 
						||
(VALUE ret)
 | 
						||
{
 | 
						||
    ret = vm_check_keyword(kw_bits_index, keyword_index, GET_EP());
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c setting
 | 
						||
  @e trace a branch
 | 
						||
  @j 分岐を trace する
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
tracebranch
 | 
						||
(rb_num_t nf, VALUE data)
 | 
						||
()
 | 
						||
()
 | 
						||
{
 | 
						||
    rb_event_flag_t flag = (rb_event_flag_t)nf;
 | 
						||
 | 
						||
    vm_dtrace(flag, ec);
 | 
						||
    EXEC_EVENT_HOOK(ec, flag, GET_SELF(), 0, 0, 0 /* id and klass are resolved at callee */, data);
 | 
						||
}
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with control flow 1: class/module                 */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c class/module
 | 
						||
  @e
 | 
						||
   enter class definition scope. if super is Qfalse, and class
 | 
						||
   "klass" is defined, it's redefine. otherwise, define "klass" class.
 | 
						||
  @j クラス定義スコープへ移行する。
 | 
						||
   もし super が Qfalse で klassクラスが定義されていれば再定義である。
 | 
						||
   そうでなければ、klass クラスを定義する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
defineclass
 | 
						||
(ID id, ISEQ class_iseq, rb_num_t flags)
 | 
						||
(VALUE cbase, VALUE super)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super);
 | 
						||
 | 
						||
    rb_iseq_check(class_iseq);
 | 
						||
 | 
						||
    /* enter scope */
 | 
						||
    vm_push_frame(ec, class_iseq, VM_FRAME_MAGIC_CLASS | VM_ENV_FLAG_LOCAL, klass,
 | 
						||
		  GET_BLOCK_HANDLER(),
 | 
						||
		  (VALUE)vm_cref_push(ec, klass, NULL, FALSE),
 | 
						||
		  class_iseq->body->iseq_encoded, GET_SP(),
 | 
						||
		  class_iseq->body->local_table_size,
 | 
						||
		  class_iseq->body->stack_max);
 | 
						||
    RESTORE_REGS();
 | 
						||
    NEXT_INSN();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with control flow 2: method/iterator              */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c method/iterator
 | 
						||
  @e invoke method.
 | 
						||
  @j メソッド呼び出しを行う。ci に必要な情報が格納されている。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
send
 | 
						||
(CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));
 | 
						||
{
 | 
						||
    struct rb_calling_info calling;
 | 
						||
 | 
						||
    vm_caller_setup_arg_block(ec, reg_cfp, &calling, ci, blockiseq, FALSE);
 | 
						||
    vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc));
 | 
						||
    CALL_METHOD(&calling, ci, cc);
 | 
						||
}
 | 
						||
 | 
						||
DEFINE_INSN
 | 
						||
opt_str_freeze
 | 
						||
(VALUE str)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    if (BASIC_OP_UNREDEFINED_P(BOP_FREEZE, STRING_REDEFINED_OP_FLAG)) {
 | 
						||
	val = str;
 | 
						||
    }
 | 
						||
    else {
 | 
						||
	val = rb_funcall(rb_str_resurrect(str), idFreeze, 0);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
DEFINE_INSN
 | 
						||
opt_str_uminus
 | 
						||
(VALUE str)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    if (BASIC_OP_UNREDEFINED_P(BOP_UMINUS, STRING_REDEFINED_OP_FLAG)) {
 | 
						||
	val = str;
 | 
						||
    }
 | 
						||
    else {
 | 
						||
	val = rb_funcall(rb_str_resurrect(str), idUMinus, 0);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
DEFINE_INSN
 | 
						||
opt_newarray_max
 | 
						||
(rb_num_t num)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - num;
 | 
						||
{
 | 
						||
    val = vm_opt_newarray_max(num, STACK_ADDR_FROM_TOP(num));
 | 
						||
    POPN(num);
 | 
						||
}
 | 
						||
 | 
						||
DEFINE_INSN
 | 
						||
opt_newarray_min
 | 
						||
(rb_num_t num)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += 1 - num;
 | 
						||
{
 | 
						||
    val = vm_opt_newarray_min(num, STACK_ADDR_FROM_TOP(num));
 | 
						||
    POPN(num);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e Invoke method without block
 | 
						||
  @j ブロックなしでメソッド呼び出しを行う。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_send_without_block
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += -ci->orig_argc;
 | 
						||
{
 | 
						||
    struct rb_calling_info calling;
 | 
						||
    calling.block_handler = VM_BLOCK_HANDLER_NONE;
 | 
						||
    vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc));
 | 
						||
    CALL_METHOD(&calling, ci, cc);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c method/iterator
 | 
						||
  @e super(args) # args.size => num
 | 
						||
  @j super を実行する。ci に必要な情報が格納されている。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
invokesuper
 | 
						||
(CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq)
 | 
						||
(...)
 | 
						||
(VALUE val) // inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));
 | 
						||
{
 | 
						||
    struct rb_calling_info calling;
 | 
						||
    calling.argc = ci->orig_argc;
 | 
						||
 | 
						||
    vm_caller_setup_arg_block(ec, reg_cfp, &calling, ci, blockiseq, TRUE);
 | 
						||
    calling.recv = GET_SELF();
 | 
						||
    vm_search_super_method(ec, GET_CFP(), &calling, ci, cc);
 | 
						||
    CALL_METHOD(&calling, ci, cc);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c method/iterator
 | 
						||
  @e yield(args)
 | 
						||
  @j yield を実行する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
invokeblock
 | 
						||
(CALL_INFO ci)
 | 
						||
(...)
 | 
						||
(VALUE val)  // inc += 1 - ci->orig_argc;
 | 
						||
{
 | 
						||
    struct rb_calling_info calling;
 | 
						||
    calling.argc = ci->orig_argc;
 | 
						||
    calling.block_handler = VM_BLOCK_HANDLER_NONE;
 | 
						||
    calling.recv = GET_SELF();
 | 
						||
 | 
						||
    val = vm_invoke_block(ec, GET_CFP(), &calling, ci);
 | 
						||
    if (val == Qundef) {
 | 
						||
	RESTORE_REGS();
 | 
						||
	NEXT_INSN();
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c method/iterator
 | 
						||
  @e return from this scope.
 | 
						||
  @j このスコープから抜ける。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
leave
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    if (OPT_CHECKED_RUN) {
 | 
						||
	const VALUE *const bp = vm_base_ptr(reg_cfp);
 | 
						||
	if (reg_cfp->sp != bp) {
 | 
						||
	    vm_stack_consistency_error(ec, reg_cfp, bp);
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
    RUBY_VM_CHECK_INTS(ec);
 | 
						||
 | 
						||
    if (vm_pop_frame(ec, GET_CFP(), GET_EP())) {
 | 
						||
#if OPT_CALL_THREADED_CODE
 | 
						||
	rb_ec_thread_ptr(ec)->retval = val;
 | 
						||
	return 0;
 | 
						||
#else
 | 
						||
	return val;
 | 
						||
#endif
 | 
						||
    }
 | 
						||
    else {
 | 
						||
	RESTORE_REGS();
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with control flow 3: exception                    */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c exception
 | 
						||
  @e longjump
 | 
						||
  @j 大域ジャンプを行う。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
throw
 | 
						||
(rb_num_t throw_state)
 | 
						||
(VALUE throwobj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    RUBY_VM_CHECK_INTS(ec);
 | 
						||
    val = vm_throw(ec, GET_CFP(), throw_state, throwobj);
 | 
						||
    THROW_EXCEPTION(val);
 | 
						||
    /* unreachable */
 | 
						||
}
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* deal with control flow 4: local jump                   */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c jump
 | 
						||
  @e set PC to (PC + dst).
 | 
						||
  @j PC を (PC + dst) にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
jump
 | 
						||
(OFFSET dst)
 | 
						||
()
 | 
						||
()
 | 
						||
{
 | 
						||
    RUBY_VM_CHECK_INTS(ec);
 | 
						||
    JUMP(dst);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c jump
 | 
						||
  @e if val is not false or nil, set PC to (PC + dst).
 | 
						||
  @j もし val が false か nil でなければ、PC を (PC + dst) にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
branchif
 | 
						||
(OFFSET dst)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    if (RTEST(val)) {
 | 
						||
	RUBY_VM_CHECK_INTS(ec);
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c jump
 | 
						||
  @e if val is false or nil, set PC to (PC + dst).
 | 
						||
  @j もし val が false か nil ならば、PC を (PC + dst) にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
branchunless
 | 
						||
(OFFSET dst)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    if (!RTEST(val)) {
 | 
						||
	RUBY_VM_CHECK_INTS(ec);
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c jump
 | 
						||
  @e if val is nil, set PC to (PC + dst).
 | 
						||
  @j もし val が nil ならば、PC を (PC + dst) にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
branchnil
 | 
						||
(OFFSET dst)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    if (NIL_P(val)) {
 | 
						||
	RUBY_VM_CHECK_INTS(ec);
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c jump
 | 
						||
  @e if val is type, set PC to (PC + dst).
 | 
						||
  @j もし val が type ならば、PC を (PC + dst) にする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
branchiftype
 | 
						||
(rb_num_t type, OFFSET dst)
 | 
						||
(VALUE val)
 | 
						||
()
 | 
						||
{
 | 
						||
    if (TYPE(val) == (int)type) {
 | 
						||
	RUBY_VM_CHECK_INTS(ec);
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**********************************************************/
 | 
						||
/* for optimize                                           */
 | 
						||
/**********************************************************/
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e push inline-cached value and go to dst if it is valid
 | 
						||
  @j インラインキャッシュが有効なら、値をスタックにプッシュして dst へジャンプする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
getinlinecache
 | 
						||
(OFFSET dst, IC ic)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_ic_hit_p(ic, GET_EP());
 | 
						||
    if (val != Qnil) {
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e set inline cache
 | 
						||
  @j インラインキャッシュの値を設定する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
setinlinecache
 | 
						||
(IC ic)
 | 
						||
(VALUE val)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    vm_ic_update(ic, val, GET_EP());
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e run iseq only once
 | 
						||
  @j once を実現する。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
once
 | 
						||
(ISEQ iseq, IC ic)
 | 
						||
()
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_once_dispatch(ec, iseq, ic);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e case dispatcher, jump by table if possible
 | 
						||
  @j case 文で、可能なら表引きでジャンプする。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_case_dispatch
 | 
						||
(CDHASH hash, OFFSET else_offset)
 | 
						||
(..., VALUE key)
 | 
						||
() // inc += -1;
 | 
						||
{
 | 
						||
    OFFSET dst = vm_case_dispatch(hash, else_offset, key);
 | 
						||
 | 
						||
    if (dst) {
 | 
						||
	JUMP(dst);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/** simple functions */
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X+Y.
 | 
						||
  @j 最適化された X+Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_plus
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_plus(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X-Y.
 | 
						||
  @j 最適化された X-Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_minus
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_minus(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X*Y.
 | 
						||
  @j 最適化された X*Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_mult
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_mult(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X/Y.
 | 
						||
  @j 最適化された X/Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_div
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_div(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X%Y.
 | 
						||
  @j 最適化された X%Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_mod
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_mod(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X==Y.
 | 
						||
  @j 最適化された X==Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_eq
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = opt_eq_func(recv, obj, ci, cc);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X!=Y.
 | 
						||
  @j 最適化された X!=Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_neq
 | 
						||
(CALL_INFO ci, CALL_CACHE cc, CALL_INFO ci_eq, CALL_CACHE cc_eq)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_neq(ci, cc, ci_eq, cc_eq, recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X<Y.
 | 
						||
  @j 最適化された X<Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_lt
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_lt(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X<=Y.
 | 
						||
  @j 最適化された X<=Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_le
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_le(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X>Y.
 | 
						||
  @j 最適化された X>Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_gt
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_gt(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized X>=Y.
 | 
						||
  @j 最適化された X>=Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_ge
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_ge(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e <<
 | 
						||
  @j 最適化された X<<Y。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_ltlt
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_ltlt(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e []
 | 
						||
  @j 最適化された recv[obj]。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_aref
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_aref(recv, obj);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e recv[obj] = set
 | 
						||
  @j 最適化された recv[obj] = set。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_aset
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv, VALUE obj, VALUE set)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_aset(recv, obj, set);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(obj);
 | 
						||
	PUSH(set);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e recv[str] = set
 | 
						||
  @j 最適化された recv[str] = set。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_aset_with
 | 
						||
(CALL_INFO ci, CALL_CACHE cc, VALUE key)
 | 
						||
(VALUE recv, VALUE val)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    VALUE tmp = vm_opt_aset_with(recv, key, val);
 | 
						||
 | 
						||
    if (tmp != Qundef) {
 | 
						||
	val = tmp;
 | 
						||
    }
 | 
						||
    else {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(rb_str_resurrect(key));
 | 
						||
	PUSH(val);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e recv[str]
 | 
						||
  @j 最適化された recv[str]。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_aref_with
 | 
						||
(CALL_INFO ci, CALL_CACHE cc, VALUE key)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_aref_with(recv, key);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	PUSH(rb_str_resurrect(key));
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized length
 | 
						||
  @j 最適化された recv.length()。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_length
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_length(recv, BOP_LENGTH);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized size
 | 
						||
  @j 最適化された recv.size()。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_size
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_length(recv, BOP_SIZE);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized empty?
 | 
						||
  @j 最適化された recv.empty?()。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_empty_p
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_empty_p(recv);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized succ
 | 
						||
  @j 最適化された recv.succ()。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_succ
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_succ(recv);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized not
 | 
						||
  @j 最適化された recv.!()。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_not
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE recv)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_not(ci, cc, recv);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(recv);
 | 
						||
	CALL_SIMPLE_METHOD(recv);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized regexp match
 | 
						||
  @j 最適化された正規表現マッチ。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_regexpmatch1
 | 
						||
(VALUE recv)
 | 
						||
(VALUE obj)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_regexpmatch1(recv, obj);
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e optimized regexp match 2
 | 
						||
  @j 最適化された正規表現マッチ 2
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_regexpmatch2
 | 
						||
(CALL_INFO ci, CALL_CACHE cc)
 | 
						||
(VALUE obj2, VALUE obj1)
 | 
						||
(VALUE val)
 | 
						||
{
 | 
						||
    val = vm_opt_regexpmatch2(obj2, obj1);
 | 
						||
 | 
						||
    if (val == Qundef) {
 | 
						||
	/* other */
 | 
						||
	PUSH(obj2);
 | 
						||
	PUSH(obj1);
 | 
						||
	CALL_SIMPLE_METHOD(obj2);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c optimize
 | 
						||
  @e call native compiled method
 | 
						||
  @j ネイティブコンパイルしたメソッドを起動。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
opt_call_c_function
 | 
						||
(rb_insn_func_t funcptr)
 | 
						||
()
 | 
						||
()
 | 
						||
{
 | 
						||
    reg_cfp = (funcptr)(ec, reg_cfp);
 | 
						||
 | 
						||
    if (reg_cfp == 0) {
 | 
						||
	VALUE err = ec->errinfo;
 | 
						||
	ec->errinfo = Qnil;
 | 
						||
	THROW_EXCEPTION(err);
 | 
						||
    }
 | 
						||
 | 
						||
    RESTORE_REGS();
 | 
						||
    NEXT_INSN();
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c joke
 | 
						||
  @e BLT
 | 
						||
  @j BLT
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
bitblt
 | 
						||
()
 | 
						||
()
 | 
						||
(VALUE ret)
 | 
						||
{
 | 
						||
    ret = rb_str_new2("a bit of bacon, lettuce and tomato");
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
  @c joke
 | 
						||
  @e The Answer to Life, the Universe, and Everything
 | 
						||
  @j 人生、宇宙、すべての答え。
 | 
						||
 */
 | 
						||
DEFINE_INSN
 | 
						||
answer
 | 
						||
()
 | 
						||
()
 | 
						||
(VALUE ret)
 | 
						||
{
 | 
						||
    ret = INT2FIX(42);
 | 
						||
}
 | 
						||
 |