+ --debug is now --imcc-debug; make this more consistent with -D.
[parrot.git] / src / runops_cores.c
blob0dfde84604fbe89e7af0df1574bc72d01e450f26
1 /*
2 Copyright (C) 2001-2006, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/runops_cores.c - Run Loops
9 =head1 DESCRIPTION
11 This file implements the various run loops for the interpreter. A slow
12 one with bounds checking, tracing and (optional) profiling, and a fast
13 one without. There's also one which uses computed C<goto>, which enables
14 the faster dispatch of operations.
16 =head2 Functions
18 =over 4
20 =cut
24 #include "runops_cores.h"
25 #include "parrot/embed.h"
26 #include "trace.h"
27 #include "interp_guts.h"
29 #ifdef HAVE_COMPUTED_GOTO
30 # include "parrot/oplib/core_ops_cg.h"
31 #endif
33 /* HEADERIZER HFILE: src/runops_cores.h */
35 /* HEADERIZER BEGIN: static */
37 PARROT_WARN_UNUSED_RESULT
38 PARROT_CAN_RETURN_NULL
39 static opcode_t * runops_trace_core(PARROT_INTERP, ARGIN(opcode_t *pc))
40 __attribute__nonnull__(1)
41 __attribute__nonnull__(2);
43 /* HEADERIZER END: static */
47 =item C<opcode_t * runops_fast_core>
49 Runs the Parrot operations starting at C<pc> until there are no more
50 operations.
52 No bounds checking, profiling or tracing is performed.
54 =cut
58 PARROT_WARN_UNUSED_RESULT
59 PARROT_CAN_RETURN_NULL
60 opcode_t *
61 runops_fast_core(PARROT_INTERP, ARGIN(opcode_t *pc))
63 while (pc) {
64 DO_OP(pc, interp);
66 return pc;
71 =item C<opcode_t * runops_cgoto_core>
73 Runs the Parrot operations starting at C<pc> until there are no more
74 operations, using the computed C<goto> core.
76 No bounds checking, profiling or tracing is performed.
78 If computed C<goto> is not available then Parrot exits with exit code 1.
80 =cut
84 PARROT_WARN_UNUSED_RESULT
85 PARROT_CAN_RETURN_NULL
86 opcode_t *
87 runops_cgoto_core(PARROT_INTERP, ARGIN(opcode_t *pc))
89 #ifdef HAVE_COMPUTED_GOTO
90 pc = cg_core(pc, interp);
91 return pc;
92 #else
93 UNUSED(pc);
94 PIO_eprintf(interp,
95 "Computed goto unavailable in this configuration.\n");
96 Parrot_exit(interp, 1);
97 #endif
100 #ifdef code_start
101 # undef code_start
102 #endif
103 #ifdef code_end
104 # undef code_end
105 #endif
107 #define code_start interp->code->base.data
108 #define code_end (interp->code->base.data + interp->code->base.size)
112 =item C<static opcode_t * runops_trace_core>
114 Runs the Parrot operations starting at C<pc> until there are no more
115 operations, using the tracing interpreter.
117 =cut
121 PARROT_WARN_UNUSED_RESULT
122 PARROT_CAN_RETURN_NULL
123 static opcode_t *
124 runops_trace_core(PARROT_INTERP, ARGIN(opcode_t *pc))
126 static size_t dod, gc;
127 Arenas * const arena_base = interp->arena_base;
128 Interp *debugger;
129 PMC* pio;
131 dod = arena_base->dod_runs;
132 gc = arena_base->collect_runs;
133 if (!interp->debugger) {
134 PMC *pio;
136 debugger = interp->debugger =
138 * using a distinct interpreter for tracing should be ok
139 * - just in case, make it easy to switch
141 #if 1
142 make_interpreter(interp, 0);
143 #else
144 interp;
145 #endif
146 debugger->lo_var_ptr = interp->lo_var_ptr;
147 pio = PIO_STDERR(debugger);
148 if (PIO_isatty(debugger, pio))
149 PIO_setlinebuf(debugger, pio);
150 else {
151 /* this is essential (100 x faster!) and should probably
152 * be in init/open code */
153 PIO_setbuf(debugger, pio, 8192);
156 else
157 debugger = interp->debugger;
158 trace_op(interp, code_start, code_end, pc);
159 while (pc) {
160 if (pc < code_start || pc >= code_end) {
161 real_exception(interp, NULL, 1,
162 "attempt to access code outside of current code segment");
164 CONTEXT(interp->ctx)->current_pc = pc;
166 DO_OP(pc, interp);
167 trace_op(interp, code_start, code_end, pc);
168 if (dod != arena_base->dod_runs) {
169 dod = arena_base->dod_runs;
170 PIO_eprintf(debugger, " DOD\n");
172 if (gc != arena_base->collect_runs) {
173 gc = arena_base->collect_runs;
174 PIO_eprintf(debugger, " GC\n");
177 pio = PIO_STDERR(debugger);
178 PIO_flush(debugger, pio);
180 return pc;
185 =item C<opcode_t * runops_slow_core>
187 Runs the Parrot operations starting at C<pc> until there are no more
188 operations, with tracing and bounds checking enabled.
190 =cut
194 PARROT_WARN_UNUSED_RESULT
195 PARROT_CAN_RETURN_NULL
196 opcode_t *
197 runops_slow_core(PARROT_INTERP, ARGIN(opcode_t *pc))
200 if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG)) {
201 return runops_trace_core(interp, pc);
203 else if (interp->debugger && interp->debugger->pdb) {
204 return Parrot_debug(interp->debugger, pc);
206 while (pc) {
207 if (pc < code_start || pc >= code_end) {
208 real_exception(interp, NULL, 1,
209 "attempt to access code outside of current code segment");
211 CONTEXT(interp->ctx)->current_pc = pc;
213 DO_OP(pc, interp);
215 return pc;
220 =item C<opcode_t * runops_gc_debug_core>
222 Runs the Parrot operations starting at C<pc> until there are no more
223 operations, performing a full GC run before each op. This is very slow, but
224 it's also a very quick way to find GC problems.
226 =cut
230 PARROT_WARN_UNUSED_RESULT
231 PARROT_CAN_RETURN_NULL
232 opcode_t *
233 runops_gc_debug_core(PARROT_INTERP, ARGIN(opcode_t *pc))
235 while (pc) {
236 if (pc < code_start || pc >= code_end) {
237 real_exception(interp, NULL, 1,
238 "attempt to access code outside of current code segment");
240 Parrot_do_dod_run(interp, 0);
241 CONTEXT(interp->ctx)->current_pc = pc;
243 DO_OP(pc, interp);
246 return pc;
249 #undef code_start
250 #undef code_end
254 =item C<opcode_t * runops_profile_core>
256 Runs the Parrot operations starting at C<pc> until there are no more
257 operations, with tracing, bounds checking and profiling enabled.
259 =cut
263 PARROT_WARN_UNUSED_RESULT
264 PARROT_CAN_RETURN_NULL
265 opcode_t *
266 runops_profile_core(PARROT_INTERP, ARGIN(opcode_t *pc))
268 RunProfile * const profile = interp->profile;
270 const opcode_t old_op = profile->cur_op;
272 * if we are reentering the runloop:
273 * - remember old op and calc time till now
275 if (old_op) {
276 profile->data[old_op].time +=
277 Parrot_floatval_time() - profile->starttime;
280 while (pc) {/* && pc >= code_start && pc < code_end) */
281 opcode_t cur_op;
282 CONTEXT(interp->ctx)->current_pc = pc;
283 profile->cur_op = cur_op = *pc + PARROT_PROF_EXTRA;
284 profile->data[cur_op].numcalls++;
285 profile->starttime = Parrot_floatval_time();
287 DO_OP(pc, interp);
289 /* profile->cur_op may be different, if exception was thrown */
290 profile->data[profile->cur_op].time +=
291 Parrot_floatval_time() - profile->starttime;
293 if (old_op) {
294 /* old opcode continues */
295 profile->starttime = Parrot_floatval_time();
296 profile->cur_op = old_op;
298 return pc;
303 =back
308 * Local variables:
309 * c-file-style: "parrot"
310 * End:
311 * vim: expandtab shiftwidth=4: