2 Copyright (C) 2001-2006, The Perl Foundation.
7 src/runops_cores.c - Run Loops
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.
22 #include "runops_cores.h"
23 #include "parrot/embed.h"
25 #include "interp_guts.h"
27 #ifdef HAVE_COMPUTED_GOTO
28 # include "parrot/oplib/core_ops_cg.h"
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.
56 PARROT_WARN_UNUSED_RESULT
57 PARROT_CAN_RETURN_NULL
59 runops_fast_core(PARROT_INTERP
, ARGIN(opcode_t
*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.
83 PARROT_WARN_UNUSED_RESULT
84 PARROT_CAN_RETURN_NULL
86 runops_cgoto_core(PARROT_INTERP
, ARGIN(opcode_t
*pc
))
88 #ifdef HAVE_COMPUTED_GOTO
89 pc
= cg_core(pc
, interp
);
94 "Computed goto unavailable in this configuration.\n");
95 Parrot_exit(interp
, 1);
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.
121 PARROT_WARN_UNUSED_RESULT
122 PARROT_CAN_RETURN_NULL
124 runops_trace_core(PARROT_INTERP
, ARGIN(opcode_t
*pc
))
126 static size_t dod
, gc
;
127 Arenas
* const arena_base
= interp
->arena_base
;
131 dod
= arena_base
->dod_runs
;
132 gc
= arena_base
->collect_runs
;
133 if (!interp
->debugger
) {
136 debugger
= interp
->debugger
=
138 * using a distinct interpreter for tracing should be ok
139 * - just in case, make it easy to switch
142 make_interpreter(interp
, 0);
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
);
155 /* this is essential (100 x faster!) and should probably
156 * be in init/open code */
157 PIO_setbuf(debugger
, pio
, 8192);
161 debugger
= interp
->debugger
;
163 trace_op(interp
, code_start
, code_end
, 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
;
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
));
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.
202 PARROT_WARN_UNUSED_RESULT
203 PARROT_CAN_RETURN_NULL
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
);
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
;
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.
240 PARROT_WARN_UNUSED_RESULT
241 PARROT_CAN_RETURN_NULL
243 runops_gc_debug_core(PARROT_INTERP
, ARGIN(opcode_t
*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
;
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.
274 PARROT_WARN_UNUSED_RESULT
275 PARROT_CAN_RETURN_NULL
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 */
284 profile
->data
[old_op
].time
+=
285 Parrot_floatval_time() - profile
->starttime
;
287 while (pc
) {/* && pc >= code_start && pc < code_end) */
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
++;
297 /* profile->cur_op may be different, if exception was thrown */
298 profile
->data
[profile
->cur_op
].time
+=
299 Parrot_floatval_time() - profile
->starttime
;
303 /* old opcode continues */
304 profile
->starttime
= Parrot_floatval_time();
305 profile
->cur_op
= old_op
;
319 * c-file-style: "parrot"
321 * vim: expandtab shiftwidth=4: