tagged release 0.6.4
[parrot.git] / src / runops_cores.c
blobb1e6554b0c67bb999ddc7ba953c4405778ff27ce
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. See
12 F<docs/running.pod> for a fuller description of the runcores and what they do.
14 =head2 Functions
16 =over 4
18 =cut
22 #include "runops_cores.h"
23 #include "parrot/embed.h"
24 #include "trace.h"
25 #include "interp_guts.h"
27 #ifdef HAVE_COMPUTED_GOTO
28 # include "parrot/oplib/core_ops_cg.h"
29 #endif
31 /* HEADERIZER HFILE: src/runops_cores.h */
33 /* HEADERIZER BEGIN: static */
34 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
36 PARROT_WARN_UNUSED_RESULT
37 PARROT_CAN_RETURN_NULL
38 static opcode_t * runops_trace_core(PARROT_INTERP, ARGIN(opcode_t *pc))
39 __attribute__nonnull__(1)
40 __attribute__nonnull__(2);
42 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
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. This performs no bounds checking, profiling, or tracing.
52 =cut
56 PARROT_WARN_UNUSED_RESULT
57 PARROT_CAN_RETURN_NULL
58 opcode_t *
59 runops_fast_core(PARROT_INTERP, ARGIN(opcode_t *pc))
61 while (pc) {
62 DO_OP(pc, interp);
65 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, performing no bounds checking,
75 profiling, or tracing.
77 If computed C<goto> is not available then Parrot exits with exit code 1.
79 =cut
83 PARROT_WARN_UNUSED_RESULT
84 PARROT_CAN_RETURN_NULL
85 opcode_t *
86 runops_cgoto_core(PARROT_INTERP, ARGIN(opcode_t *pc))
88 #ifdef HAVE_COMPUTED_GOTO
89 pc = cg_core(pc, interp);
90 return pc;
91 #else
92 UNUSED(pc);
93 PIO_eprintf(interp,
94 "Computed goto unavailable in this configuration.\n");
95 Parrot_exit(interp, 1);
96 #endif
99 #ifdef code_start
100 # undef code_start
101 #endif
102 #ifdef code_end
103 # undef code_end
104 #endif
106 #define code_start interp->code->base.data
107 #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 /* set the top of the stack so GC can trace it for GC-able pointers
147 * see trace_system_areas() in src/cpu_dep.c */
148 debugger->lo_var_ptr = interp->lo_var_ptr;
150 pio = PIO_STDERR(debugger);
152 if (PIO_isatty(debugger, pio))
153 PIO_setlinebuf(debugger, pio);
154 else {
155 /* this is essential (100 x faster!) and should probably
156 * be in init/open code */
157 PIO_setbuf(debugger, pio, 8192);
160 else
161 debugger = interp->debugger;
163 trace_op(interp, code_start, code_end, pc);
164 while (pc) {
165 if (pc < code_start || pc >= code_end)
166 real_exception(interp, NULL, 1,
167 "attempt to access code outside of current code segment");
169 CONTEXT(interp)->current_pc = pc;
171 DO_OP(pc, interp);
172 trace_op(interp, code_start, code_end, pc);
174 if (dod != arena_base->dod_runs) {
175 dod = arena_base->dod_runs;
176 PIO_eprintf(debugger, " DOD\n");
179 if (gc != arena_base->collect_runs) {
180 gc = arena_base->collect_runs;
181 PIO_eprintf(debugger, " GC\n");
185 PIO_flush(debugger, PIO_STDERR(debugger));
187 return pc;
193 =item C<opcode_t * runops_slow_core>
195 Runs the Parrot operations starting at C<pc> until there are no more
196 operations, with tracing and bounds checking enabled.
198 =cut
202 PARROT_WARN_UNUSED_RESULT
203 PARROT_CAN_RETURN_NULL
204 opcode_t *
205 runops_slow_core(PARROT_INTERP, ARGIN(opcode_t *pc))
208 if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG))
209 return runops_trace_core(interp, pc);
211 if (interp->debugger && interp->debugger->pdb)
212 return Parrot_debug(interp->debugger, pc);
214 while (pc) {
215 if (pc < code_start || pc >= code_end)
216 real_exception(interp, NULL, 1,
217 "attempt to access code outside of current code segment");
219 CONTEXT(interp)->current_pc = pc;
221 DO_OP(pc, interp);
224 return pc;
230 =item C<opcode_t * runops_gc_debug_core>
232 Runs the Parrot operations starting at C<pc> until there are no more
233 operations, performing a full GC run before each op. This is very slow, but
234 it's also a very quick way to find GC problems.
236 =cut
240 PARROT_WARN_UNUSED_RESULT
241 PARROT_CAN_RETURN_NULL
242 opcode_t *
243 runops_gc_debug_core(PARROT_INTERP, ARGIN(opcode_t *pc))
245 while (pc) {
246 if (pc < code_start || pc >= code_end)
247 real_exception(interp, NULL, 1,
248 "attempt to access code outside of current code segment");
250 Parrot_do_dod_run(interp, 0);
251 CONTEXT(interp)->current_pc = pc;
253 DO_OP(pc, interp);
256 return pc;
259 #undef code_start
260 #undef code_end
265 =item C<opcode_t * runops_profile_core>
267 Runs the Parrot operations starting at C<pc> until there are no more
268 operations, with tracing, bounds checking, and profiling enabled.
270 =cut
274 PARROT_WARN_UNUSED_RESULT
275 PARROT_CAN_RETURN_NULL
276 opcode_t *
277 runops_profile_core(PARROT_INTERP, ARGIN(opcode_t *pc))
279 RunProfile * const profile = interp->profile;
280 const opcode_t old_op = profile->cur_op;
282 /* if reentering the runloop, remember old op and calc time 'til now */
283 if (old_op)
284 profile->data[old_op].time +=
285 Parrot_floatval_time() - profile->starttime;
287 while (pc) {/* && pc >= code_start && pc < code_end) */
288 opcode_t cur_op;
290 CONTEXT(interp)->current_pc = pc;
291 profile->cur_op = cur_op = *pc + PARROT_PROF_EXTRA;
292 profile->starttime = Parrot_floatval_time();
293 profile->data[cur_op].numcalls++;
295 DO_OP(pc, interp);
297 /* profile->cur_op may be different, if exception was thrown */
298 profile->data[profile->cur_op].time +=
299 Parrot_floatval_time() - profile->starttime;
302 if (old_op) {
303 /* old opcode continues */
304 profile->starttime = Parrot_floatval_time();
305 profile->cur_op = old_op;
308 return pc;
313 =back
318 * Local variables:
319 * c-file-style: "parrot"
320 * End:
321 * vim: expandtab shiftwidth=4: