00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <math.h>
00013
00014 #if VM_COLLECT_USAGE_DETAILS
00015 static void vm_analysis_insn(int insn);
00016 #endif
00017
00018 #if VMDEBUG > 0
00019 #define DECL_SC_REG(type, r, reg) register type reg_##r
00020
00021 #elif defined(__GNUC__) && defined(__x86_64__)
00022 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
00023
00024 #elif defined(__GNUC__) && defined(__i386__)
00025 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
00026
00027 #else
00028 #define DECL_SC_REG(type, r, reg) register type reg_##r
00029 #endif
00030
00031
00032 #if VM_DEBUG_STACKOVERFLOW
00033 NORETURN(static void vm_stack_overflow_for_insn(void));
00034 static void
00035 vm_stack_overflow_for_insn(void)
00036 {
00037 rb_bug("CHECK_VM_STACK_OVERFLOW_FOR_INSN: should not overflow here. "
00038 "Please contact ruby-core/dev with your (a part of) script. "
00039 "This check will be removed soon.");
00040 }
00041 #endif
00042
00043 #if !OPT_CALL_THREADED_CODE
00044 static VALUE
00045 vm_exec_core(rb_thread_t *th, VALUE initial)
00046 {
00047
00048 #if OPT_STACK_CACHING
00049 #if 0
00050 #elif __GNUC__ && __x86_64__
00051 DECL_SC_REG(VALUE, a, "12");
00052 DECL_SC_REG(VALUE, b, "13");
00053 #else
00054 register VALUE reg_a;
00055 register VALUE reg_b;
00056 #endif
00057 #endif
00058
00059 #if defined(__GNUC__) && defined(__i386__)
00060 DECL_SC_REG(VALUE *, pc, "di");
00061 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
00062 #define USE_MACHINE_REGS 1
00063
00064 #elif defined(__GNUC__) && defined(__x86_64__)
00065 DECL_SC_REG(VALUE *, pc, "14");
00066 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
00067 #define USE_MACHINE_REGS 1
00068
00069 #else
00070 register rb_control_frame_t *reg_cfp;
00071 VALUE *reg_pc;
00072 #endif
00073
00074 #if USE_MACHINE_REGS
00075
00076 #undef RESTORE_REGS
00077 #define RESTORE_REGS() \
00078 { \
00079 REG_CFP = th->cfp; \
00080 reg_pc = reg_cfp->pc; \
00081 }
00082
00083 #undef REG_PC
00084 #define REG_PC reg_pc
00085 #undef GET_PC
00086 #define GET_PC() (reg_pc)
00087 #undef SET_PC
00088 #define SET_PC(x) (reg_cfp->pc = REG_PC = (x))
00089 #endif
00090
00091 #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
00092 #include "vmtc.inc"
00093 if (UNLIKELY(th == 0)) {
00094 return (VALUE)insns_address_table;
00095 }
00096 #endif
00097 reg_cfp = th->cfp;
00098 reg_pc = reg_cfp->pc;
00099
00100 #if OPT_STACK_CACHING
00101 reg_a = initial;
00102 reg_b = 0;
00103 #endif
00104
00105 first:
00106 INSN_DISPATCH();
00107
00108 #include "vm.inc"
00109
00110 END_INSNS_DISPATCH();
00111
00112
00113 rb_bug("vm_eval: unreachable");
00114 goto first;
00115 }
00116
00117 const void **
00118 rb_vm_get_insns_address_table(void)
00119 {
00120 return (const void **)vm_exec_core(0, 0);
00121 }
00122
00123 #else
00124
00125 #include "vm.inc"
00126 #include "vmtc.inc"
00127
00128 const void **
00129 rb_vm_get_insns_address_table(void)
00130 {
00131 return (const void **)insns_address_table;
00132 }
00133
00134 static VALUE
00135 vm_exec_core(rb_thread_t *th, VALUE initial)
00136 {
00137 register rb_control_frame_t *reg_cfp = th->cfp;
00138
00139 while (1) {
00140 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(th, reg_cfp);
00141
00142 if (UNLIKELY(reg_cfp == 0)) {
00143 break;
00144 }
00145 }
00146
00147 if (th->retval != Qundef) {
00148 VALUE ret = th->retval;
00149 th->retval = Qundef;
00150 return ret;
00151 }
00152 else {
00153 VALUE err = th->errinfo;
00154 th->errinfo = Qnil;
00155 return err;
00156 }
00157 }
00158 #endif
00159