2 /**********************************************************************
8 Copyright (C) 2004-2007 Koichi Sasada
10 **********************************************************************/
14 #if VM_COLLECT_USAGE_DETAILS
15 static void vm_analysis_insn(int insn
);
18 MAYBE_UNUSED(static void vm_insns_counter_count_insn(int insn
));
20 static size_t rb_insns_counter
[VM_INSTRUCTION_SIZE
];
23 vm_insns_counter_count_insn(int insn
)
25 rb_insns_counter
[insn
]++;
28 __attribute__((destructor
))
30 vm_insns_counter_show_results_at_exit(void)
32 int insn_end
= (ruby_vm_event_enabled_global_flags
& ISEQ_TRACE_EVENTS
)
33 ? VM_INSTRUCTION_SIZE
: VM_INSTRUCTION_SIZE
/ 2;
36 for (int insn
= 0; insn
< insn_end
; insn
++)
37 total
+= rb_insns_counter
[insn
];
39 for (int insn
= 0; insn
< insn_end
; insn
++) {
40 fprintf(stderr
, "[RUBY_INSNS_COUNTER]\t%-32s%'12"PRIuSIZE
" (%4.1f%%)\n",
41 insn_name(insn
), rb_insns_counter
[insn
],
42 100.0 * rb_insns_counter
[insn
] / total
);
46 static void vm_insns_counter_count_insn(int insn
) {}
50 #define DECL_SC_REG(type, r, reg) register type reg_##r
52 #elif defined(__GNUC__) && defined(__x86_64__)
53 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
55 #elif defined(__GNUC__) && defined(__i386__)
56 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("e" reg)
58 #elif defined(__GNUC__) && defined(__powerpc64__)
59 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("r" reg)
61 #elif defined(__GNUC__) && defined(__aarch64__)
62 #define DECL_SC_REG(type, r, reg) register type reg_##r __asm__("x" reg)
65 #define DECL_SC_REG(type, r, reg) register type reg_##r
67 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
69 #if !OPT_CALL_THREADED_CODE
71 vm_exec_core(rb_execution_context_t
*ec
, VALUE initial
)
76 #elif __GNUC__ && __x86_64__
77 DECL_SC_REG(VALUE
, a
, "12");
78 DECL_SC_REG(VALUE
, b
, "13");
85 #if defined(__GNUC__) && defined(__i386__)
86 DECL_SC_REG(const VALUE
*, pc
, "di");
87 DECL_SC_REG(rb_control_frame_t
*, cfp
, "si");
88 #define USE_MACHINE_REGS 1
90 #elif defined(__GNUC__) && defined(__x86_64__)
91 DECL_SC_REG(const VALUE
*, pc
, "14");
92 DECL_SC_REG(rb_control_frame_t
*, cfp
, "15");
93 #define USE_MACHINE_REGS 1
95 #elif defined(__GNUC__) && defined(__powerpc64__)
96 DECL_SC_REG(const VALUE
*, pc
, "14");
97 DECL_SC_REG(rb_control_frame_t
*, cfp
, "15");
98 #define USE_MACHINE_REGS 1
100 #elif defined(__GNUC__) && defined(__aarch64__)
101 DECL_SC_REG(const VALUE
*, pc
, "19");
102 DECL_SC_REG(rb_control_frame_t
*, cfp
, "20");
103 #define USE_MACHINE_REGS 1
106 register rb_control_frame_t
*reg_cfp
;
108 #define USE_MACHINE_REGS 0
115 #define RESTORE_REGS() \
117 VM_REG_CFP = ec->cfp; \
118 reg_pc = reg_cfp->pc; \
122 #define VM_REG_PC reg_pc
124 #define GET_PC() (reg_pc)
126 #define SET_PC(x) (reg_cfp->pc = VM_REG_PC = (x))
129 #if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
131 if (UNLIKELY(ec
== 0)) {
132 return (VALUE
)insns_address_table
;
136 reg_pc
= reg_cfp
->pc
;
138 #if OPT_STACK_CACHING
148 END_INSNS_DISPATCH();
151 rb_bug("vm_eval: unreachable");
156 rb_vm_get_insns_address_table(void)
158 return (const void **)vm_exec_core(0, 0);
161 #else /* OPT_CALL_THREADED_CODE */
167 rb_vm_get_insns_address_table(void)
169 return (const void **)insns_address_table
;
173 vm_exec_core(rb_execution_context_t
*ec
, VALUE initial
)
175 register rb_control_frame_t
*reg_cfp
= ec
->cfp
;
179 reg_cfp
= ((rb_insn_func_t
) (*GET_PC()))(ec
, reg_cfp
);
181 if (UNLIKELY(reg_cfp
== 0)) {
186 if ((th
= rb_ec_thread_ptr(ec
))->retval
!= Qundef
) {
187 VALUE ret
= th
->retval
;
192 VALUE err
= ec
->errinfo
;