Ruby  2.0.0p247(2013-06-27revision41674)
vm_exec.h
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   vm.h -
00004 
00005   $Author: nagachika $
00006   created at: 04/01/01 16:56:59 JST
00007 
00008   Copyright (C) 2004-2007 Koichi Sasada
00009 
00010 **********************************************************************/
00011 
00012 #ifndef RUBY_VM_EXEC_H
00013 #define RUBY_VM_EXEC_H
00014 
00015 typedef long OFFSET;
00016 typedef unsigned long lindex_t;
00017 typedef VALUE GENTRY;
00018 typedef rb_iseq_t *ISEQ;
00019 
00020 #ifdef __GCC__
00021 /* TODO: machine dependent prefetch instruction */
00022 #define PREFETCH(pc)
00023 #else
00024 #define PREFETCH(pc)
00025 #endif
00026 
00027 #if VMDEBUG > 0
00028 #define debugs printf
00029 #define DEBUG_ENTER_INSN(insn) \
00030   rb_vmdebug_debug_print_pre(th, GET_CFP());
00031 
00032 #if OPT_STACK_CACHING
00033 #define SC_REGS() , reg_a, reg_b
00034 #else
00035 #define SC_REGS()
00036 #endif
00037 
00038 #define DEBUG_END_INSN() \
00039   rb_vmdebug_debug_print_post(th, GET_CFP() SC_REGS());
00040 
00041 #else
00042 
00043 #define debugs
00044 #define DEBUG_ENTER_INSN(insn)
00045 #define DEBUG_END_INSN()
00046 #endif
00047 
00048 #define throwdebug if(0)printf
00049 /* #define throwdebug printf */
00050 
00051 /************************************************/
00052 #if defined(DISPATCH_XXX)
00053 error !
00054 /************************************************/
00055 #elif OPT_CALL_THREADED_CODE
00056 
00057 #define LABEL(x)  insn_func_##x
00058 #define ELABEL(x)
00059 #define LABEL_PTR(x) &LABEL(x)
00060 
00061 #define INSN_ENTRY(insn) \
00062   static rb_control_frame_t * \
00063     FUNC_FASTCALL(LABEL(insn))(rb_thread_t *th, rb_control_frame_t *reg_cfp) {
00064 
00065 #define END_INSN(insn) return reg_cfp;}
00066 
00067 #define NEXT_INSN() return reg_cfp;
00068 
00069 /************************************************/
00070 #elif OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
00071 /* threaded code with gcc */
00072 
00073 #define LABEL(x)  INSN_LABEL_##x
00074 #define ELABEL(x) INSN_ELABEL_##x
00075 #define LABEL_PTR(x) &&LABEL(x)
00076 
00077 #define INSN_ENTRY_SIG(insn)
00078 
00079 
00080 #define INSN_DISPATCH_SIG(insn)
00081 
00082 #define INSN_ENTRY(insn) \
00083   LABEL(insn): \
00084   INSN_ENTRY_SIG(insn); \
00085 
00086 /* dispatcher */
00087 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && __GNUC__ == 3
00088 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
00089   asm volatile("jmp *%0;\t# -- inseted by vm.h\t[length = 2]" : : "r" (addr))
00090 
00091 #else
00092 #define DISPATCH_ARCH_DEPEND_WAY(addr) \
00093                                 /* do nothing */
00094 
00095 #endif
00096 
00097 
00098 /**********************************/
00099 #if OPT_DIRECT_THREADED_CODE
00100 
00101 /* for GCC 3.4.x */
00102 #define TC_DISPATCH(insn) \
00103   INSN_DISPATCH_SIG(insn); \
00104   goto *(void const *)GET_CURRENT_INSN(); \
00105   ;
00106 
00107 #else
00108 /* token threaded code */
00109 
00110 #define TC_DISPATCH(insn)  \
00111   DISPATCH_ARCH_DEPEND_WAY(insns_address_table[GET_CURRENT_INSN()]); \
00112   INSN_DISPATCH_SIG(insn); \
00113   goto *insns_address_table[GET_CURRENT_INSN()]; \
00114   rb_bug("tc error");
00115 
00116 
00117 #endif /* DISPATCH_DIRECT_THREADED_CODE */
00118 
00119 #define END_INSN(insn)      \
00120   DEBUG_END_INSN();         \
00121   TC_DISPATCH(insn);        \
00122 
00123 #define INSN_DISPATCH()     \
00124   TC_DISPATCH(__START__)    \
00125   {
00126 
00127 #define END_INSNS_DISPATCH()    \
00128       rb_bug("unknown insn: %"PRIdVALUE, GET_CURRENT_INSN());   \
00129   }   /* end of while loop */   \
00130 
00131 #define NEXT_INSN() TC_DISPATCH(__NEXT_INSN__)
00132 
00133 /************************************************/
00134 #else /* no threaded code */
00135 /* most common method */
00136 
00137 #define INSN_ENTRY(insn) \
00138 case BIN(insn):
00139 
00140 #define END_INSN(insn)                        \
00141   DEBUG_END_INSN();                           \
00142   break;
00143 
00144 
00145 #define INSN_DISPATCH()         \
00146   while (1) {                   \
00147     switch (GET_CURRENT_INSN()) {
00148 
00149 #define END_INSNS_DISPATCH()    \
00150 default:                        \
00151   SDR(); \
00152       rb_bug("unknown insn: %ld", GET_CURRENT_INSN());   \
00153     } /* end of switch */       \
00154   }   /* end of while loop */   \
00155 
00156 #define NEXT_INSN() goto first
00157 
00158 #endif
00159 
00160 #define VM_SP_CNT(th, sp) ((sp) - (th)->stack)
00161 
00162 #if OPT_CALL_THREADED_CODE
00163 #define THROW_EXCEPTION(exc) do { \
00164     th->errinfo = (VALUE)(exc); \
00165     return 0; \
00166 } while (0)
00167 #else
00168 #define THROW_EXCEPTION(exc) return (VALUE)(exc)
00169 #endif
00170 
00171 #define SCREG(r) (reg_##r)
00172 
00173 #endif /* RUBY_VM_EXEC_H */
00174