Ruby 1.9.3p327(2012-11-10revision37606)
|
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__ 00018 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg) 00019 00020 #elif __GNUC__ && __i386__ 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