Ruby  2.0.0p247(2013-06-27revision41674)
vm_exec.c
Go to the documentation of this file.
00001 /* -*-c-*- */
00002 /**********************************************************************
00003 
00004   vm_exec.c -
00005 
00006   $Author: nagachika $
00007 
00008   Copyright (C) 2004-2007 Koichi Sasada
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 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
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     /* unreachable */
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 /* OPT_CALL_THREADED_CODE */
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