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 !OPT_CALL_THREADED_CODE
00033 static VALUE
00034 vm_exec_core(rb_thread_t *th, VALUE initial)
00035 {
00036
00037 #if OPT_STACK_CACHING
00038 #if 0
00039 #elif __GNUC__ && __x86_64__
00040 DECL_SC_REG(VALUE, a, "12");
00041 DECL_SC_REG(VALUE, b, "13");
00042 #else
00043 register VALUE reg_a;
00044 register VALUE reg_b;
00045 #endif
00046 #endif
00047
00048 #if defined(__GNUC__) && defined(__i386__)
00049 DECL_SC_REG(VALUE *, pc, "di");
00050 DECL_SC_REG(rb_control_frame_t *, cfp, "si");
00051 #define USE_MACHINE_REGS 1
00052
00053 #elif defined(__GNUC__) && defined(__x86_64__)
00054 DECL_SC_REG(VALUE *, pc, "14");
00055 DECL_SC_REG(rb_control_frame_t *, cfp, "15");
00056 #define USE_MACHINE_REGS 1
00057
00058 #else
00059 register rb_control_frame_t *reg_cfp;
00060 VALUE *reg_pc;
00061 #endif
00062
00063 #if USE_MACHINE_REGS
00064
00065 #undef RESTORE_REGS
00066 #define RESTORE_REGS() \
00067 { \
00068 REG_CFP = th->cfp; \
00069 reg_pc = reg_cfp->pc; \
00070 }
00071
00072 #undef REG_PC
00073 #define REG_PC reg_pc
00074 #undef GET_PC
00075 #define GET_PC() (reg_pc)
00076 #undef SET_PC
00077 #define SET_PC(x) (reg_cfp->pc = REG_PC = (x))
00078 #endif
00079
00080 #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
00081 #include "vmtc.inc"
00082 if (UNLIKELY(th == 0)) {
00083 return (VALUE)insns_address_table;
00084 }
00085 #endif
00086 reg_cfp = th->cfp;
00087 reg_pc = reg_cfp->pc;
00088
00089 #if OPT_STACK_CACHING
00090 reg_a = initial;
00091 reg_b = 0;
00092 #endif
00093
00094 first:
00095 INSN_DISPATCH();
00096
00097 #include "vm.inc"
00098
00099 END_INSNS_DISPATCH();
00100
00101
00102 rb_bug("vm_eval: unreachable");
00103 goto first;
00104 }
00105
00106 const void **
00107 rb_vm_get_insns_address_table(void)
00108 {
00109 return (const void **)vm_exec_core(0, 0);
00110 }
00111
00112 #else
00113
00114 #include "vm.inc"
00115 #include "vmtc.inc"
00116
00117 const void **
00118 rb_vm_get_insns_address_table(void)
00119 {
00120 return (const void **)insns_address_table;
00121 }
00122
00123 static VALUE
00124 vm_exec_core(rb_thread_t *th, VALUE initial)
00125 {
00126 register rb_control_frame_t *reg_cfp = th->cfp;
00127
00128 while (1) {
00129 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(th, reg_cfp);
00130
00131 if (UNLIKELY(reg_cfp == 0)) {
00132 break;
00133 }
00134 }
00135
00136 if (th->retval != Qundef) {
00137 VALUE ret = th->retval;
00138 th->retval = Qundef;
00139 return ret;
00140 }
00141 else {
00142 VALUE err = th->errinfo;
00143 th->errinfo = Qnil;
00144 return err;
00145 }
00146 }
00147 #endif
00148