Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

vm_exec.c
Go to the documentation of this file.
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
15 static 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
33 static VALUE
34 vm_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
106 const void **
107 rb_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
117 const void **
118 rb_vm_get_insns_address_table(void)
119 {
120 return (const void **)insns_address_table;
121 }
122
123 static VALUE
124 vm_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