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