1/* -*-c-*- */ 2/********************************************************************** 3 4 vm_exec.c - 5 6 $Author: nagachika $ 7 8 Copyright (C) 2004-2007 Koichi Sasada 9 10**********************************************************************/ 11 12#include <math.h> 13 14#if VM_COLLECT_USAGE_DETAILS 15static void vm_analysis_insn(int insn); 16#endif 17 18#if VMDEBUG > 0 19#define DECL_SC_REG(type, r, reg) register type reg_##r 20 21#elif defined(__GNUC__) && defined(__x86_64__) 22#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg) 23 24#elif defined(__GNUC__) && defined(__i386__) 25#define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg) 26 27#else 28#define DECL_SC_REG(type, r, reg) register type reg_##r 29#endif 30/* #define DECL_SC_REG(r, reg) VALUE reg_##r */ 31 32#if !OPT_CALL_THREADED_CODE 33static VALUE 34vm_exec_core(rb_thread_t *th, VALUE initial) 35{ 36 37#if OPT_STACK_CACHING 38#if 0 39#elif __GNUC__ && __x86_64__ 40 DECL_SC_REG(VALUE, a, "12"); 41 DECL_SC_REG(VALUE, b, "13"); 42#else 43 register VALUE reg_a; 44 register VALUE reg_b; 45#endif 46#endif 47 48#if defined(__GNUC__) && defined(__i386__) 49 DECL_SC_REG(VALUE *, pc, "di"); 50 DECL_SC_REG(rb_control_frame_t *, cfp, "si"); 51#define USE_MACHINE_REGS 1 52 53#elif defined(__GNUC__) && defined(__x86_64__) 54 DECL_SC_REG(VALUE *, pc, "14"); 55 DECL_SC_REG(rb_control_frame_t *, cfp, "15"); 56#define USE_MACHINE_REGS 1 57 58#else 59 register rb_control_frame_t *reg_cfp; 60 VALUE *reg_pc; 61#endif 62 63#if USE_MACHINE_REGS 64 65#undef RESTORE_REGS 66#define RESTORE_REGS() \ 67{ \ 68 REG_CFP = th->cfp; \ 69 reg_pc = reg_cfp->pc; \ 70} 71 72#undef REG_PC 73#define REG_PC reg_pc 74#undef GET_PC 75#define GET_PC() (reg_pc) 76#undef SET_PC 77#define SET_PC(x) (reg_cfp->pc = REG_PC = (x)) 78#endif 79 80#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE 81#include "vmtc.inc" 82 if (UNLIKELY(th == 0)) { 83 return (VALUE)insns_address_table; 84 } 85#endif 86 reg_cfp = th->cfp; 87 reg_pc = reg_cfp->pc; 88 89#if OPT_STACK_CACHING 90 reg_a = initial; 91 reg_b = 0; 92#endif 93 94 first: 95 INSN_DISPATCH(); 96/*****************/ 97 #include "vm.inc" 98/*****************/ 99 END_INSNS_DISPATCH(); 100 101 /* unreachable */ 102 rb_bug("vm_eval: unreachable"); 103 goto first; 104} 105 106const void ** 107rb_vm_get_insns_address_table(void) 108{ 109 return (const void **)vm_exec_core(0, 0); 110} 111 112#else /* OPT_CALL_THREADED_CODE */ 113 114#include "vm.inc" 115#include "vmtc.inc" 116 117const void ** 118rb_vm_get_insns_address_table(void) 119{ 120 return (const void **)insns_address_table; 121} 122 123static VALUE 124vm_exec_core(rb_thread_t *th, VALUE initial) 125{ 126 register rb_control_frame_t *reg_cfp = th->cfp; 127 128 while (1) { 129 reg_cfp = ((rb_insn_func_t) (*GET_PC()))(th, reg_cfp); 130 131 if (UNLIKELY(reg_cfp == 0)) { 132 break; 133 } 134 } 135 136 if (th->retval != Qundef) { 137 VALUE ret = th->retval; 138 th->retval = Qundef; 139 return ret; 140 } 141 else { 142 VALUE err = th->errinfo; 143 th->errinfo = Qnil; 144 return err; 145 } 146} 147#endif 148