• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

vm_exec.c

Go to the documentation of this file.
00001 /* -*-c-*- */
00002 /**********************************************************************
00003 
00004   vm_exec.c -
00005 
00006   $Author: naruse $
00007 
00008   Copyright (C) 2004-2007 Koichi Sasada
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 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
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     /* unreachable */
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); /* pop */
00153     th->cfp++; /* pop cf */
00154     return ret;
00155 }
00156 #endif
00157 

Generated on Wed Sep 8 2010 21:55:25 for Ruby by  doxygen 1.7.1