vm_exec.c

Go to the documentation of this file.
00001 /* -*-c-*- */
00002 /**********************************************************************
00003 
00004   vm_exec.c -
00005 
00006   $Author: ko1 $
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 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     /* unreachable */
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 /* OPT_CALL_THREADED_CODE */
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 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7