aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--insns.def773
-rw-r--r--internal.h1
-rw-r--r--vm_insnhelper.c866
3 files changed, 977 insertions, 663 deletions
diff --git a/insns.def b/insns.def
index a4f2526bef..2fcb1b0c48 100644
--- a/insns.def
+++ b/insns.def
@@ -57,14 +57,7 @@ getlocal
()
(VALUE val)
{
- int i, lev = (int)level;
- const VALUE *ep = GET_EP();
-
- /* optimized insns generated for level == (0|1) in defs/opt_operand.def */
- for (i = 0; i < lev; i++) {
- ep = GET_PREV_EP(ep);
- }
- val = *(ep - idx);
+ val = *(vm_get_ep(GET_EP(), level) - idx);
}
/**
@@ -80,14 +73,7 @@ setlocal
(VALUE val)
()
{
- int i, lev = (int)level;
- const VALUE *ep = GET_EP();
-
- /* optimized insns generated for level == (0|1) in defs/opt_operand.def */
- for (i = 0; i < lev; i++) {
- ep = GET_PREV_EP(ep);
- }
- vm_env_write(ep, -(int)idx, val);
+ vm_env_write(vm_get_ep(GET_EP(), level), -(int)idx, val);
}
/**
@@ -311,21 +297,10 @@ putspecialobject
()
(VALUE val)
{
- enum vm_special_object_type type = (enum vm_special_object_type)value_type;
-
- switch (type) {
- case VM_SPECIAL_OBJECT_VMCORE:
- val = rb_mRubyVMFrozenCore;
- break;
- case VM_SPECIAL_OBJECT_CBASE:
- val = vm_get_cbase(GET_EP());
- break;
- case VM_SPECIAL_OBJECT_CONST_BASE:
- val = vm_get_const_base(GET_EP());
- break;
- default:
- rb_bug("putspecialobject insn: unknown value_type");
- }
+ enum vm_special_object_type type;
+
+ type = (enum vm_special_object_type)value_type;
+ val = vm_get_special_object(GET_EP(), type);
}
/**
@@ -367,7 +342,7 @@ concatstrings
(...)
(VALUE val) // inc += 1 - num;
{
- val = rb_str_concat_literals(num, &TOPN(num-1));
+ val = rb_str_concat_literals(num, STACK_ADDR_FROM_TOP(num));
POPN(num);
}
@@ -396,10 +371,7 @@ freezestring
(VALUE str)
(VALUE str)
{
- if (!NIL_P(debug_info)) {
- rb_ivar_set(str, id_debug_created_info, debug_info);
- }
- rb_str_freeze(str);
+ vm_freezestring(str, debug_info);
}
/**
@@ -437,7 +409,7 @@ newarray
(...)
(VALUE val) // inc += 1 - num;
{
- val = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
+ val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
POPN(num);
}
@@ -491,25 +463,10 @@ expandarray
DEFINE_INSN
concatarray
()
-(VALUE ary1, VALUE ary2st)
+(VALUE ary1, VALUE ary2)
(VALUE ary)
{
- const VALUE ary2 = ary2st;
- VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a");
- VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a");
-
- if (NIL_P(tmp1)) {
- tmp1 = rb_ary_new3(1, ary1);
- }
-
- if (NIL_P(tmp2)) {
- tmp2 = rb_ary_new3(1, ary2);
- }
-
- if (tmp1 == ary1) {
- tmp1 = rb_ary_dup(ary1);
- }
- ary = rb_ary_concat(tmp1, tmp2);
+ ary = vm_concat_array(ary1, ary2);
}
/**
@@ -523,14 +480,7 @@ splatarray
(VALUE ary)
(VALUE obj)
{
- VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
- if (NIL_P(tmp)) {
- tmp = rb_ary_new3(1, ary);
- }
- else if (RTEST(flag)) {
- tmp = rb_ary_dup(tmp);
- }
- obj = tmp;
+ obj = vm_splat_array(flag, ary);
}
/**
@@ -617,12 +567,11 @@ dupn
(...)
(...) // inc += n;
{
- rb_num_t i;
- VALUE *sp = STACK_ADDR_FROM_TOP(n);
- for (i = 0; i < n; i++) {
- GET_SP()[i] = sp[i];
- }
- INC_SP(n);
+ void *dst = GET_SP();
+ void *src = STACK_ADDR_FROM_TOP(n);
+
+ INC_SP(n); /* alloca */
+ MEMCPY(dst, src, VALUE, n);
}
@@ -753,24 +702,7 @@ checkmatch
(VALUE target, VALUE pattern)
(VALUE result)
{
- enum vm_check_match_type checkmatch_type =
- (enum vm_check_match_type)(flag & VM_CHECKMATCH_TYPE_MASK);
- result = Qfalse;
-
- if (flag & VM_CHECKMATCH_ARRAY) {
- long i;
- for (i = 0; i < RARRAY_LEN(pattern); i++) {
- if (RTEST(check_match(RARRAY_AREF(pattern, i), target, checkmatch_type))) {
- result = Qtrue;
- break;
- }
- }
- }
- else {
- if (RTEST(check_match(pattern, target, checkmatch_type))) {
- result = Qtrue;
- }
- }
+ result = vm_check_match(target, pattern, flag)
}
/**
@@ -784,17 +716,7 @@ checkkeyword
()
(VALUE ret)
{
- const VALUE *ep = GET_EP();
- const VALUE kw_bits = *(ep - kw_bits_index);
-
- if (FIXNUM_P(kw_bits)) {
- int bits = FIX2INT(kw_bits);
- ret = (bits & (0x01 << keyword_index)) ? Qfalse : Qtrue;
- }
- else {
- VM_ASSERT(RB_TYPE_P(kw_bits, T_HASH));
- ret = rb_hash_has_key(kw_bits, INT2FIX(keyword_index)) ? Qfalse : Qtrue;
- }
+ ret = vm_check_keyword(kw_bits_index, keyword_index, GET_EP());
}
/**
@@ -810,27 +732,7 @@ trace
{
rb_event_flag_t flag = (rb_event_flag_t)nf;
- if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
- RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
- RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
- RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
-
- switch (flag) {
- case RUBY_EVENT_CALL:
- RUBY_DTRACE_METHOD_ENTRY_HOOK(th, 0, 0);
- break;
- case RUBY_EVENT_C_CALL:
- RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, 0, 0);
- break;
- case RUBY_EVENT_RETURN:
- RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0);
- break;
- case RUBY_EVENT_C_RETURN:
- RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, 0, 0);
- break;
- }
- }
-
+ vm_dtrace(nf, th);
EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0, 0 /* id and klass are resolved at callee */,
(flag & (RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN)) ? TOPN(0) : Qundef);
}
@@ -854,82 +756,7 @@ defineclass
(VALUE cbase, VALUE super)
(VALUE val)
{
- VALUE klass;
- rb_vm_defineclass_type_t type = VM_DEFINECLASS_TYPE(flags);
-
- switch (type) {
- case VM_DEFINECLASS_TYPE_CLASS:
- /* val is dummy. classdef returns class scope value */
-
- if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) &&
- !RB_TYPE_P(super, T_CLASS)) {
- rb_raise(rb_eTypeError, "superclass must be a Class (%"PRIsVALUE" given)",
- rb_obj_class(super));
- }
-
- vm_check_if_namespace(cbase);
-
- /* find klass */
- rb_autoload_load(cbase, id);
- if ((klass = vm_search_const_defined_class(cbase, id)) != 0) {
- /* already exist */
- klass = VM_DEFINECLASS_SCOPED_P(flags) ?
- rb_public_const_get_at(klass, id) : rb_const_get_at(klass, id);
- if (!RB_TYPE_P(klass, T_CLASS)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" is not a class", rb_id2str(id));
- }
-
- if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
- VALUE tmp;
- tmp = rb_class_real(RCLASS_SUPER(klass));
-
- if (tmp != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class %"PRIsVALUE"",
- rb_id2str(id));
- }
- }
- }
- else {
- if (!VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
- super = rb_cObject;
- }
- /* new class declaration */
- klass = rb_define_class_id(id, super);
- rb_set_class_path_string(klass, cbase, rb_id2str(id));
- rb_const_set(cbase, id, klass);
- rb_class_inherited(super, klass);
- }
- break;
- case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
- /* val is dummy. classdef returns class scope value */
- /* super is dummy */
- klass = rb_singleton_class(cbase);
- break;
- case VM_DEFINECLASS_TYPE_MODULE:
- /* val is dummy. classdef returns class scope value */
- /* super is dummy */
-
- vm_check_if_namespace(cbase);
-
- /* find klass */
- if ((klass = vm_search_const_defined_class(cbase, id)) != 0) {
- klass = VM_DEFINECLASS_SCOPED_P(flags) ?
- rb_public_const_get_at(klass, id) : rb_const_get_at(klass, id);
- /* already exist */
- if (!RB_TYPE_P(klass, T_MODULE)) {
- rb_raise(rb_eTypeError, "%"PRIsVALUE" is not a module", rb_id2str(id));
- }
- }
- else {
- /* new module declaration */
- klass = rb_define_module_id(id);
- rb_set_class_path_string(klass, cbase, rb_id2str(id));
- rb_const_set(cbase, id, klass);
- }
- break;
- default:
- rb_bug("unknown defineclass type: %d", (int)type);
- }
+ VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super);
rb_iseq_check(class_iseq);
@@ -1001,32 +828,8 @@ opt_newarray_max
(...)
(VALUE val) // inc += 1 - num;
{
-#define id_cmp idCmp
- if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
- if (num == 0) {
- val = Qnil;
- }
- else {
- struct cmp_opt_data cmp_opt = { 0, 0 };
- VALUE result = Qundef;
- rb_num_t i = num - 1;
- result = TOPN(i);
- while (i-- > 0) {
- const VALUE v = TOPN(i);
- if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
- result = v;
- }
- }
- val = result == Qundef ? Qnil : result;
- }
- POPN(num);
- }
- else {
- VALUE ary = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
- val = rb_funcall(ary, idMax, 0);
- POPN(num);
- }
-#undef id_cmp
+ val = vm_opt_newarray_max(num, STACK_ADDR_FROM_TOP(num));
+ POPN(num);
}
DEFINE_INSN
@@ -1035,32 +838,8 @@ opt_newarray_min
(...)
(VALUE val) // inc += 1 - num;
{
-#define id_cmp idCmp
- if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
- if (num == 0) {
- val = Qnil;
- }
- else {
- struct cmp_opt_data cmp_opt = { 0, 0 };
- VALUE result = Qundef;
- rb_num_t i = num - 1;
- result = TOPN(i);
- while (i-- > 0) {
- const VALUE v = TOPN(i);
- if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
- result = v;
- }
- }
- val = result == Qundef ? Qnil : result;
- }
- POPN(num);
- }
- else {
- VALUE ary = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
- val = rb_funcall(ary, idMin, 0);
- POPN(num);
- }
-#undef id_cmp
+ val = vm_opt_newarray_min(num, STACK_ADDR_FROM_TOP(num));
+ POPN(num);
}
/**
@@ -1264,15 +1043,10 @@ getinlinecache
()
(VALUE val)
{
- if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE() &&
- (ic->ic_cref == NULL || ic->ic_cref == rb_vm_get_cref(GET_EP()))) {
- val = ic->ic_value.value;
+ val = vm_ic_hit_p(ic, GET_EP());
+ if (val != Qnil) {
JUMP(dst);
}
- else {
- /* none */
- val = Qnil;
- }
}
/**
@@ -1286,11 +1060,7 @@ setinlinecache
(VALUE val)
(VALUE val)
{
- VM_ASSERT(ic->ic_value.value != Qundef);
- ic->ic_value.value = val;
- ic->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count;
- ic->ic_cref = vm_get_const_key_cref(GET_EP());
- ruby_vm_const_missing_count = 0;
+ vm_ic_update(ic, val, GET_EP());
}
/**
@@ -1304,30 +1074,7 @@ once
()
(VALUE val)
{
- union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)ic;
-
-#define RUNNING_THREAD_ONCE_DONE ((rb_thread_t *)(0x1))
- retry:
- if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
- val = is->once.value;
- }
- else if (is->once.running_thread == NULL) {
- is->once.running_thread = th;
- val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is);
- /* is->once.running_thread is cleared by vm_once_clear() */
- is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */
- rb_iseq_add_mark_object(GET_ISEQ(), val);
- }
- else if (is->once.running_thread == th) {
- /* recursive once */
- val = vm_once_exec((VALUE)iseq);
- }
- else {
- /* waiting for finish */
- RUBY_VM_CHECK_INTS(th);
- rb_thread_schedule();
- goto retry;
- }
+ val = vm_once_dispatch(iseq, ic, th);
}
/**
@@ -1341,34 +1088,10 @@ opt_case_dispatch
(..., VALUE key)
() // inc += -1;
{
- switch (OBJ_BUILTIN_TYPE(key)) {
- case -1:
- case T_FLOAT:
- case T_SYMBOL:
- case T_BIGNUM:
- case T_STRING:
- if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
- SYMBOL_REDEFINED_OP_FLAG |
- INTEGER_REDEFINED_OP_FLAG |
- FLOAT_REDEFINED_OP_FLAG |
- NIL_REDEFINED_OP_FLAG |
- TRUE_REDEFINED_OP_FLAG |
- FALSE_REDEFINED_OP_FLAG |
- STRING_REDEFINED_OP_FLAG)) {
- st_data_t val;
- if (RB_FLOAT_TYPE_P(key)) {
- double kval = RFLOAT_VALUE(key);
- if (!isinf(kval) && modf(kval, &kval) == 0.0) {
- key = FIXABLE(kval) ? LONG2FIX((long)kval) : rb_dbl2big(kval);
- }
- }
- if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
- JUMP(FIX2INT((VALUE)val));
- }
- else {
- JUMP(else_offset);
- }
- }
+ OFFSET dst = vm_case_dispatch(hash, else_offset, key);
+
+ if (dst) {
+ JUMP(dst);
}
}
@@ -1385,33 +1108,10 @@ opt_plus
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS,INTEGER_REDEFINED_OP_FLAG)) {
- val = rb_fix_plus_fix(recv, obj);
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
- }
- else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
- if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
- }
- else if (RBASIC_CLASS(recv) == rb_cString && RBASIC_CLASS(obj) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
- val = rb_str_plus(recv, obj);
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
- val = rb_ary_plus(recv, obj);
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_plus(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1429,26 +1129,10 @@ opt_minus
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
- val = rb_fix_minus_fix(recv, obj);
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
- }
- else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
- if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
+ val = vm_opt_minus(recv, obj);
+
+ if (val == Qundef) {
/* other */
- INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1466,25 +1150,10 @@ opt_mult
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
- val = rb_fix_mul_fix(recv, obj);
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
- }
- else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
- if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_mult(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1502,26 +1171,10 @@ opt_div
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
- if (FIX2LONG(obj) == 0) goto INSN_LABEL(normal_dispatch);
- val = rb_fix_div_fix(recv, obj);
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
- }
- else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
- if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_div(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1539,26 +1192,10 @@ opt_mod
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG )) {
- if (FIX2LONG(obj) == 0) goto INSN_LABEL(normal_dispatch);
- val = rb_fix_mod_fix(recv, obj);
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
- }
- else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
- if (RBASIC_CLASS(recv) == rb_cFloat && RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
- val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_mod(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1597,18 +1234,7 @@ opt_neq
(VALUE recv, VALUE obj)
(VALUE val)
{
- extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
- vm_search_method(ci, cc, recv);
-
- val = Qundef;
-
- if (check_cfunc(cc->me, rb_obj_not_equal)) {
- val = opt_eq_func(recv, obj, ci_eq, cc_eq);
-
- if (val != Qundef) {
- val = RTEST(val) ? Qfalse : Qtrue;
- }
- }
+ val = vm_opt_neq(ci, cc, ci_eq, cc_eq, recv, obj);
if (val == Qundef) {
/* other */
@@ -1629,27 +1255,10 @@ opt_lt
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
- SIGNED_VALUE a = recv, b = obj;
+ val = vm_opt_lt(recv, obj);
- if (a < b) {
- val = Qtrue;
- }
- else {
- val = Qfalse;
- }
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
- /* flonum is not NaN */
- val = RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- }
- else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
- val = double_cmp_lt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- }
- else {
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1667,27 +1276,9 @@ opt_le
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
- SIGNED_VALUE a = recv, b = obj;
+ val = vm_opt_le(recv, obj);
- if (a <= b) {
- val = Qtrue;
- }
- else {
- val = Qfalse;
- }
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
- /* flonum is not NaN */
- val = RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- }
- else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
- val = double_cmp_le(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- }
- else {
+ if (val == Qundef) {
/* other */
PUSH(recv);
PUSH(obj);
@@ -1706,27 +1297,10 @@ opt_gt
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
- SIGNED_VALUE a = recv, b = obj;
+ val = vm_opt_gt(recv, obj);
- if (a > b) {
- val = Qtrue;
- }
- else {
- val = Qfalse;
- }
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
- /* flonum is not NaN */
- val = RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- }
- else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
- val = double_cmp_gt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- }
- else {
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1744,27 +1318,10 @@ opt_ge
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
- SIGNED_VALUE a = recv, b = obj;
+ val = vm_opt_ge(recv, obj);
- if (a >= b) {
- val = Qtrue;
- }
- else {
- val = Qfalse;
- }
- }
- else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
- /* flonum is not NaN */
- val = RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- }
- else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
- BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
- val = double_cmp_ge(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- }
- else {
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1782,21 +1339,10 @@ opt_ltlt
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
- val = rb_str_concat(recv, obj);
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
- val = rb_ary_push(recv, obj);
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_ltlt(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1814,19 +1360,10 @@ opt_aref
(VALUE recv, VALUE obj)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) {
- val = rb_ary_entry(recv, FIX2LONG(obj));
- }
- else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
- val = rb_hash_aref(recv, obj);
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_aref(recv, obj);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
CALL_SIMPLE_METHOD(recv);
@@ -1844,21 +1381,10 @@ opt_aset
(VALUE recv, VALUE obj, VALUE set)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) && FIXNUM_P(obj)) {
- rb_ary_store(recv, FIX2LONG(obj), set);
- val = set;
- }
- else if (RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
- rb_hash_aset(recv, obj, set);
- val = set;
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_aset(recv, obj, set);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(obj);
PUSH(set);
@@ -1877,12 +1403,13 @@ opt_aset_with
(VALUE recv, VALUE val)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash &&
- BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG) &&
- rb_hash_compare_by_id_p(recv) == Qfalse) {
- rb_hash_aset(recv, key, 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);
@@ -1901,12 +1428,10 @@ opt_aref_with
(VALUE recv)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash &&
- BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG) &&
- rb_hash_compare_by_id_p(recv) == Qfalse) {
- val = rb_hash_aref(recv, key);
- }
- else {
+ val = vm_opt_aref_with(recv, key);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
PUSH(rb_str_resurrect(key));
CALL_SIMPLE_METHOD(recv);
@@ -1924,25 +1449,10 @@ opt_length
(VALUE recv)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_LENGTH, STRING_REDEFINED_OP_FLAG)) {
- val = rb_str_length(recv);
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_LENGTH, ARRAY_REDEFINED_OP_FLAG)) {
- val = LONG2NUM(RARRAY_LEN(recv));
- }
- else if (RBASIC_CLASS(recv) == rb_cHash &&
- BASIC_OP_UNREDEFINED_P(BOP_LENGTH, HASH_REDEFINED_OP_FLAG)) {
- val = INT2FIX(RHASH_SIZE(recv));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_length(recv, BOP_LENGTH);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
CALL_SIMPLE_METHOD(recv);
}
@@ -1959,25 +1469,10 @@ opt_size
(VALUE recv)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_SIZE, STRING_REDEFINED_OP_FLAG)) {
- val = rb_str_length(recv);
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_SIZE, ARRAY_REDEFINED_OP_FLAG)) {
- val = LONG2NUM(RARRAY_LEN(recv));
- }
- else if (RBASIC_CLASS(recv) == rb_cHash &&
- BASIC_OP_UNREDEFINED_P(BOP_SIZE, HASH_REDEFINED_OP_FLAG)) {
- val = INT2FIX(RHASH_SIZE(recv));
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_length(recv, BOP_SIZE);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
CALL_SIMPLE_METHOD(recv);
}
@@ -1994,28 +1489,10 @@ opt_empty_p
(VALUE recv)
(VALUE val)
{
- if (!SPECIAL_CONST_P(recv)) {
- if (RBASIC_CLASS(recv) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, STRING_REDEFINED_OP_FLAG)) {
- if (RSTRING_LEN(recv) == 0) val = Qtrue;
- else val = Qfalse;
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, ARRAY_REDEFINED_OP_FLAG)) {
- if (RARRAY_LEN(recv) == 0) val = Qtrue;
- else val = Qfalse;
- }
- else if (RBASIC_CLASS(recv) == rb_cHash &&
- BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, HASH_REDEFINED_OP_FLAG)) {
- if (RHASH_EMPTY_P(recv)) val = Qtrue;
- else val = Qfalse;
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_empty_p(recv);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
CALL_SIMPLE_METHOD(recv);
}
@@ -2032,32 +1509,10 @@ opt_succ
(VALUE recv)
(VALUE val)
{
- if (SPECIAL_CONST_P(recv)) {
- if (FIXNUM_P(recv) &&
- BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
- /* fixnum + INT2FIX(1) */
- if (recv != LONG2FIX(FIXNUM_MAX)) {
- val = recv - 1 + INT2FIX(1);
- }
- else {
- val = LONG2NUM(FIXNUM_MAX + 1);
- }
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- else {
- if (RBASIC_CLASS(recv) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
- val = rb_str_succ(recv);
- }
- else {
- goto INSN_LABEL(normal_dispatch);
- }
- }
- if (0) {
- INSN_LABEL(normal_dispatch):
+ val = vm_opt_succ(recv);
+
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
CALL_SIMPLE_METHOD(recv);
}
@@ -2074,12 +1529,10 @@ opt_not
(VALUE recv)
(VALUE val)
{
- vm_search_method(ci, cc, recv);
+ val = vm_opt_not(ci, cc, recv);
- if (check_cfunc(cc->me, rb_obj_not)) {
- val = RTEST(recv) ? Qfalse : Qtrue;
- }
- else {
+ if (val == Qundef) {
+ /* other */
PUSH(recv);
CALL_SIMPLE_METHOD(recv);
}
@@ -2093,16 +1546,11 @@ opt_not
*/
DEFINE_INSN
opt_regexpmatch1
-(VALUE r)
+(VALUE recv)
(VALUE obj)
(VALUE val)
{
- if (BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
- val = rb_reg_match(r, obj);
- }
- else {
- val = rb_funcall(r, idEqTilde, 1, obj);
- }
+ val = vm_opt_regexpmatch1(recv, obj);
}
/**
@@ -2116,11 +1564,10 @@ opt_regexpmatch2
(VALUE obj2, VALUE obj1)
(VALUE val)
{
- if (CLASS_OF(obj2) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
- val = rb_reg_match(obj1, obj2);
- }
- else {
+ val = vm_opt_regexpmatch2(obj2, obj1);
+
+ if (val == Qundef) {
+ /* other */
PUSH(obj2);
PUSH(obj1);
CALL_SIMPLE_METHOD(obj2);
diff --git a/internal.h b/internal.h
index a6f7ef87f8..afea318376 100644
--- a/internal.h
+++ b/internal.h
@@ -1421,6 +1421,7 @@ NORETURN(void rb_undefined_alloc(VALUE klass));
double rb_num_to_dbl(VALUE val);
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
+VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
struct RBasicRaw {
VALUE flags;
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index fd259fd428..a2367876dc 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2880,3 +2880,869 @@ vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE
return Qnil;
}
}
+
+static const VALUE *
+vm_get_ep(const VALUE *const reg_ep, rb_num_t lv)
+{
+ rb_num_t i;
+ const VALUE *ep = reg_ep;
+ for (i = 0; i < lv; i++) {
+ ep = GET_PREV_EP(ep);
+ }
+ return ep;
+}
+
+static VALUE
+vm_get_special_object(const VALUE *const reg_ep,
+ enum vm_special_object_type type)
+{
+ switch (type) {
+ case VM_SPECIAL_OBJECT_VMCORE:
+ return rb_mRubyVMFrozenCore;
+ case VM_SPECIAL_OBJECT_CBASE:
+ return vm_get_cbase(reg_ep);
+ case VM_SPECIAL_OBJECT_CONST_BASE:
+ return vm_get_const_base(reg_ep);
+ default:
+ rb_bug("putspecialobject insn: unknown value_type %d", type);
+ }
+}
+
+static void
+vm_freezestring(VALUE str, VALUE debug)
+{
+ if (!NIL_P(debug)) {
+ rb_ivar_set(str, id_debug_created_info, debug);
+ }
+ rb_str_freeze(str);
+}
+
+static VALUE
+vm_concat_array(VALUE ary1, VALUE ary2st)
+{
+ const VALUE ary2 = ary2st;
+ VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a");
+ VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a");
+
+ if (NIL_P(tmp1)) {
+ tmp1 = rb_ary_new3(1, ary1);
+ }
+
+ if (NIL_P(tmp2)) {
+ tmp2 = rb_ary_new3(1, ary2);
+ }
+
+ if (tmp1 == ary1) {
+ tmp1 = rb_ary_dup(ary1);
+ }
+ return rb_ary_concat(tmp1, tmp2);
+}
+
+static VALUE
+vm_splat_array(VALUE flag, VALUE ary)
+{
+ VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
+ if (NIL_P(tmp)) {
+ return rb_ary_new3(1, ary);
+ }
+ else if (RTEST(flag)) {
+ return rb_ary_dup(tmp);
+ }
+ else {
+ return tmp;
+ }
+}
+
+static VALUE
+vm_check_match(VALUE target, VALUE pattern, rb_num_t flag)
+{
+ enum vm_check_match_type type = ((int)flag) & VM_CHECKMATCH_TYPE_MASK;
+
+ if (flag & VM_CHECKMATCH_ARRAY) {
+ long i;
+ const long n = RARRAY_LEN(pattern);
+
+ for (i = 0; i < n; i++) {
+ VALUE v = RARRAY_AREF(pattern, i);
+ VALUE c = check_match(v, target, type);
+
+ if (RTEST(c)) {
+ return c;
+ }
+ }
+ return Qfalse;
+ }
+ else {
+ return check_match(pattern, target, type);
+ }
+}
+
+static VALUE
+vm_check_keyword(lindex_t bits, lindex_t idx, const VALUE *ep)
+{
+ const VALUE kw_bits = *(ep - bits);
+
+ if (FIXNUM_P(kw_bits)) {
+ int b = FIX2INT(kw_bits);
+ return (b & (0x01 << idx)) ? Qfalse : Qtrue;
+ }
+ else {
+ VM_ASSERT(RB_TYPE_P(kw_bits, T_HASH));
+ return rb_hash_has_key(kw_bits, INT2FIX(idx));
+ }
+}
+
+static void
+vm_dtrace(rb_event_flag_t flag, rb_thread_t *th)
+{
+ if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
+ RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
+ RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
+ RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
+
+ switch (flag) {
+ case RUBY_EVENT_CALL:
+ RUBY_DTRACE_METHOD_ENTRY_HOOK(th, 0, 0);
+ return;
+ case RUBY_EVENT_C_CALL:
+ RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, 0, 0);
+ return;
+ case RUBY_EVENT_RETURN:
+ RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0);
+ return;
+ case RUBY_EVENT_C_RETURN:
+ RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, 0, 0);
+ return;
+ }
+ }
+}
+
+static VALUE
+vm_const_get_under(ID id, rb_num_t flags, VALUE cbase)
+{
+ VALUE ns;
+
+ if ((ns = vm_search_const_defined_class(cbase, id)) == 0) {
+ return ns;
+ }
+ else if (VM_DEFINECLASS_SCOPED_P(flags)) {
+ return rb_public_const_get_at(ns, id);
+ }
+ else {
+ return rb_const_get_at(ns, id);
+ }
+}
+
+static VALUE
+vm_check_if_class(ID id, rb_num_t flags, VALUE super, VALUE klass)
+{
+ if (!RB_TYPE_P(klass, T_CLASS)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" is not a class", rb_id2str(id));
+ }
+ else if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags)) {
+ VALUE tmp = rb_class_real(RCLASS_SUPER(klass));
+
+ if (tmp != super) {
+ rb_raise(rb_eTypeError,
+ "superclass mismatch for class %"PRIsVALUE"",
+ rb_id2str(id));
+ }
+ else {
+ return klass;
+ }
+ }
+ else {
+ return klass;
+ }
+}
+
+static VALUE
+vm_check_if_module(ID id, VALUE mod)
+{
+ if (!RB_TYPE_P(mod, T_MODULE)) {
+ rb_raise(rb_eTypeError, "%"PRIsVALUE" is not a module", rb_id2str(id));
+ }
+ else {
+ return mod;
+ }
+}
+
+static VALUE
+vm_declare_class(ID id, rb_num_t flags, VALUE cbase, VALUE super)
+{
+ /* new class declaration */
+ VALUE s = VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) ? super : rb_cObject;
+ VALUE c = rb_define_class_id(id, s);
+
+ rb_set_class_path_string(c, cbase, rb_id2str(id));
+ rb_const_set(cbase, id, c);
+ rb_class_inherited(s, c);
+ return c;
+}
+
+static VALUE
+vm_declare_module(ID id, VALUE cbase)
+{
+ /* new module declaration */
+ VALUE mod = rb_define_module_id(id);
+ rb_set_class_path_string(mod, cbase, rb_id2str(id));
+ rb_const_set(cbase, id, mod);
+ return mod;
+}
+
+static VALUE
+vm_define_class(ID id, rb_num_t flags, VALUE cbase, VALUE super)
+{
+ VALUE klass;
+
+ if (VM_DEFINECLASS_HAS_SUPERCLASS_P(flags) && !RB_TYPE_P(super, T_CLASS)) {
+ rb_raise(rb_eTypeError,
+ "superclass must be a Class (%"PRIsVALUE" given)",
+ rb_obj_class(super));
+ }
+
+ vm_check_if_namespace(cbase);
+
+ /* find klass */
+ rb_autoload_load(cbase, id);
+ if ((klass = vm_const_get_under(id, flags, cbase)) != 0) {
+ return vm_check_if_class(id, flags, super, klass);
+ }
+ else {
+ return vm_declare_class(id, flags, cbase, super);
+ }
+}
+
+static VALUE
+vm_define_module(ID id, rb_num_t flags, VALUE cbase)
+{
+ VALUE mod;
+
+ vm_check_if_namespace(cbase);
+ if ((mod = vm_const_get_under(id, flags, cbase)) != 0) {
+ return vm_check_if_module(id, mod);
+ }
+ else {
+ return vm_declare_module(id, cbase);
+ }
+}
+
+static VALUE
+vm_find_or_create_class_by_id(ID id,
+ rb_num_t flags,
+ VALUE cbase,
+ VALUE super)
+{
+ rb_vm_defineclass_type_t type = VM_DEFINECLASS_TYPE(flags);
+
+ switch (type) {
+ case VM_DEFINECLASS_TYPE_CLASS:
+ /* classdef returns class scope value */
+ return vm_define_class(id, flags, cbase, super);
+
+ case VM_DEFINECLASS_TYPE_SINGLETON_CLASS:
+ /* classdef returns class scope value */
+ return rb_singleton_class(cbase);
+
+ case VM_DEFINECLASS_TYPE_MODULE:
+ /* classdef returns class scope value */
+ return vm_define_module(id, flags, cbase);
+
+ default:
+ rb_bug("unknown defineclass type: %d", (int)type);
+ }
+}
+
+/* this macro is mandatory to use OPTIMIZED_CMP. What a design! */
+#define id_cmp idCmp
+
+static VALUE
+vm_opt_newarray_max(rb_num_t num, const VALUE *ptr)
+{
+ if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
+ if (num == 0) {
+ return Qnil;
+ }
+ else {
+ struct cmp_opt_data cmp_opt = { 0, 0 };
+ VALUE result = Qundef;
+ rb_num_t i = num - 1;
+ result = ptr[i];
+ while (i-- > 0) {
+ const VALUE v = ptr[i];
+ if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
+ result = v;
+ }
+ }
+ return result == Qundef ? Qnil : result;
+ }
+ }
+ else {
+ VALUE ary = rb_ary_new4(num, ptr);
+ return rb_funcall(ary, idMax, 0);
+ }
+}
+
+static VALUE
+vm_opt_newarray_min(rb_num_t num, const VALUE *ptr)
+{
+ if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
+ if (num == 0) {
+ return Qnil;
+ }
+ else {
+ struct cmp_opt_data cmp_opt = { 0, 0 };
+ VALUE result = Qundef;
+ rb_num_t i = num - 1;
+ result = ptr[i];
+ while (i-- > 0) {
+ const VALUE v = ptr[i];
+ if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
+ result = v;
+ }
+ }
+ return result == Qundef ? Qnil : result;
+ }
+ }
+ else {
+ VALUE ary = rb_ary_new4(num, ptr);
+ return rb_funcall(ary, idMin, 0);
+ }
+}
+
+#undef id_cmp
+
+static VALUE
+vm_ic_hit_p(IC ic, const VALUE *reg_ep)
+{
+ if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE() &&
+ (ic->ic_cref == NULL || ic->ic_cref == rb_vm_get_cref(reg_ep))) {
+ return ic->ic_value.value;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+static void
+vm_ic_update(IC ic, VALUE val, const VALUE *reg_ep)
+{
+ VM_ASSERT(ic->ic_value.value != Qundef);
+ ic->ic_value.value = val;
+ ic->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count;
+ ic->ic_cref = vm_get_const_key_cref(reg_ep);
+ ruby_vm_const_missing_count = 0;
+}
+
+static VALUE
+vm_once_dispatch(ISEQ iseq, IC ic, rb_thread_t *th)
+{
+ rb_thread_t *const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1);
+ union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)ic;
+
+ if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
+ return is->once.value;
+ }
+ else if (is->once.running_thread == NULL) {
+ VALUE val;
+ is->once.running_thread = th;
+ val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is);
+ /* is->once.running_thread is cleared by vm_once_clear() */
+ is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */
+ rb_iseq_add_mark_object(th->cfp->iseq, val);
+ return val;
+ }
+ else if (is->once.running_thread == th) {
+ /* recursive once */
+ return vm_once_exec((VALUE)iseq);
+ }
+ else {
+ /* waiting for finish */
+ RUBY_VM_CHECK_INTS(th);
+ rb_thread_schedule();
+ return vm_once_dispatch(iseq, ic, th);
+ }
+}
+
+static OFFSET
+vm_case_dispatch(CDHASH hash, OFFSET else_offset, VALUE key)
+{
+ switch (OBJ_BUILTIN_TYPE(key)) {
+ case -1:
+ case T_FLOAT:
+ case T_SYMBOL:
+ case T_BIGNUM:
+ case T_STRING:
+ if (BASIC_OP_UNREDEFINED_P(BOP_EQQ,
+ SYMBOL_REDEFINED_OP_FLAG |
+ INTEGER_REDEFINED_OP_FLAG |
+ FLOAT_REDEFINED_OP_FLAG |
+ NIL_REDEFINED_OP_FLAG |
+ TRUE_REDEFINED_OP_FLAG |
+ FALSE_REDEFINED_OP_FLAG |
+ STRING_REDEFINED_OP_FLAG)) {
+ st_data_t val;
+ if (RB_FLOAT_TYPE_P(key)) {
+ double kval = RFLOAT_VALUE(key);
+ if (!isinf(kval) && modf(kval, &kval) == 0.0) {
+ key = FIXABLE(kval) ? LONG2FIX((long)kval) : rb_dbl2big(kval);
+ }
+ }
+ if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
+ return FIX2INT((VALUE)val);
+ }
+ else {
+ return else_offset;
+ }
+ }
+ }
+ return 0;
+}
+
+static VALUE
+vm_opt_plus(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS,INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_plus_fix(recv, obj);
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
+ }
+ else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
+ if (RBASIC_CLASS(recv) == rb_cString && RBASIC_CLASS(obj) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
+ return rb_str_plus(recv, obj);
+ }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
+ return rb_ary_plus(recv, obj);
+ }
+ else {
+ return Qundef;
+ }
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_minus(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_minus_fix(recv, obj);
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_mult(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_mul_fix(recv, obj);
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_div(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
+ if (FIX2LONG(obj) == 0) {
+ return Qundef;
+ }
+ else {
+ return rb_fix_div_fix(recv, obj);
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_mod(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG )) {
+ if (FIX2LONG(obj) == 0) {
+ return Qundef;
+ }
+ else {
+ return rb_fix_mod_fix(recv, obj);
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static inline int
+vm_method_cfunc_is(CALL_INFO ci, CALL_CACHE cc,
+ VALUE recv, VALUE (*func)())
+{
+ vm_search_method(ci, cc, recv);
+ return check_cfunc(cc->me, func);
+}
+
+static VALUE
+vm_opt_neq(CALL_INFO ci, CALL_CACHE cc,
+ CALL_INFO ci_eq, CALL_CACHE cc_eq,
+ VALUE recv, VALUE obj)
+{
+ if (vm_method_cfunc_is(ci, cc, recv, rb_obj_not_equal)) {
+ VALUE val = opt_eq_func(recv, obj, ci_eq, cc_eq);
+
+ if (val != Qundef) {
+ return RTEST(val) ? Qfalse : Qtrue;
+ }
+ }
+
+ return Qundef;
+}
+
+static VALUE
+vm_opt_lt(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
+ SIGNED_VALUE a = recv, b = obj;
+
+ if (a < b) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+ /* flonum is not NaN */
+ return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+ return double_cmp_lt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_le(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
+ SIGNED_VALUE a = recv, b = obj;
+
+ if (a <= b) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
+ /* flonum is not NaN */
+ return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+ return double_cmp_le(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_gt(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
+ SIGNED_VALUE a = recv, b = obj;
+
+ if (a > b) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+ /* flonum is not NaN */
+ return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+ return double_cmp_gt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_ge(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
+ SIGNED_VALUE a = recv, b = obj;
+
+ if (a >= b) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
+ /* flonum is not NaN */
+ return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+ return double_cmp_ge(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_ltlt(VALUE recv, VALUE obj)
+{
+ if (SPECIAL_CONST_P(recv)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) {
+ return rb_str_concat(recv, obj);
+ }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_LTLT, ARRAY_REDEFINED_OP_FLAG)) {
+ return rb_ary_push(recv, obj);
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_aref(VALUE recv, VALUE obj)
+{
+ if (SPECIAL_CONST_P(recv)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_AREF, ARRAY_REDEFINED_OP_FLAG) &&
+ FIXNUM_P(obj)) {
+ return rb_ary_entry(recv, FIX2LONG(obj));
+ }
+ else if (RBASIC_CLASS(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
+ return rb_hash_aref(recv, obj);
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_aset(VALUE recv, VALUE obj, VALUE set)
+{
+ if (SPECIAL_CONST_P(recv)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_ASET, ARRAY_REDEFINED_OP_FLAG) &&
+ FIXNUM_P(obj)) {
+ rb_ary_store(recv, FIX2LONG(obj), set);
+ return set;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
+ rb_hash_aset(recv, obj, set);
+ return set;
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_aref_with(VALUE recv, VALUE key)
+{
+ if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG) &&
+ rb_hash_compare_by_id_p(recv) == Qfalse) {
+ return rb_hash_aref(recv, key);
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_aset_with(VALUE recv, VALUE key, VALUE val)
+{
+ if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG) &&
+ rb_hash_compare_by_id_p(recv) == Qfalse) {
+ return rb_hash_aset(recv, key, val);
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_length(VALUE recv, int bop)
+{
+ if (SPECIAL_CONST_P(recv)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(bop, STRING_REDEFINED_OP_FLAG)) {
+ if (bop == BOP_EMPTY_P) {
+ return LONG2NUM(RSTRING_LEN(recv));
+ }
+ else {
+ return rb_str_length(recv);
+ }
+ }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
+ return LONG2NUM(RARRAY_LEN(recv));
+ }
+ else if (RBASIC_CLASS(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(bop, HASH_REDEFINED_OP_FLAG)) {
+ return INT2FIX(RHASH_SIZE(recv));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_empty_p(VALUE recv)
+{
+ switch (vm_opt_length(recv, BOP_EMPTY_P)) {
+ case Qundef: return Qundef;
+ case INT2FIX(0): return Qtrue;
+ default: return Qfalse;
+ }
+}
+
+static VALUE
+vm_opt_succ(VALUE recv)
+{
+ if (SPECIAL_CONST_P(recv)) {
+ if (FIXNUM_P(recv) &&
+ BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
+ /* fixnum + INT2FIX(1) */
+ if (recv == LONG2FIX(FIXNUM_MAX)) {
+ return LONG2NUM(FIXNUM_MAX + 1);
+ }
+ else {
+ return recv - 1 + INT2FIX(1);
+ }
+ }
+ else {
+ return Qundef;
+ }
+ }
+ else {
+ if (RBASIC_CLASS(recv) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
+ return rb_str_succ(recv);
+ }
+ else {
+ return Qundef;
+ }
+ }
+}
+
+static VALUE
+vm_opt_not(CALL_INFO ci, CALL_CACHE cc, VALUE recv)
+{
+ if (vm_method_cfunc_is(ci, cc, recv, rb_obj_not)) {
+ return RTEST(recv) ? Qfalse : Qtrue;
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_regexpmatch1(VALUE recv, VALUE obj)
+{
+ if (BASIC_OP_UNREDEFINED_P(BOP_MATCH, REGEXP_REDEFINED_OP_FLAG)) {
+ return rb_reg_match(recv, obj);
+ }
+ else {
+ return rb_funcall(recv, idEqTilde, 1, obj);
+ }
+}
+
+static VALUE
+vm_opt_regexpmatch2(VALUE recv, VALUE obj)
+{
+ if (CLASS_OF(obj) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_MATCH, STRING_REDEFINED_OP_FLAG)) {
+ return rb_reg_match(recv, obj);
+ }
+ else {
+ return Qundef;
+ }
+}
+