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. 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.
24 #include "runops_cores.h"
25 #include "parrot/embed.h"
27 #include "interp_guts.h"
29 #ifdef HAVE_COMPUTED_GOTO
30 # include "parrot/oplib/core_ops_cg.h"
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
52 No bounds checking, profiling or tracing is performed.
58 PARROT_WARN_UNUSED_RESULT
59 PARROT_CAN_RETURN_NULL
61 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.
76 No bounds checking, profiling or tracing is performed.
78 If computed C<goto> is not available then Parrot exits with exit code 1.
84 PARROT_WARN_UNUSED_RESULT
85 PARROT_CAN_RETURN_NULL
87 runops_cgoto_core(PARROT_INTERP
, ARGIN(opcode_t
*pc
))
89 #ifdef HAVE_COMPUTED_GOTO
90 pc
= cg_core(pc
, interp
);
95 "Computed goto unavailable in this configuration.\n");
96 Parrot_exit(interp
, 1);
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.
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 debugger
->lo_var_ptr
= interp
->lo_var_ptr
;
147 pio
= PIO_STDERR(debugger
);
148 if (PIO_isatty(debugger
, pio
))
149 PIO_setlinebuf(debugger
, pio
);
151 /* this is essential (100 x faster!) and should probably
152 * be in init/open code */
153 PIO_setbuf(debugger
, pio
, 8192);
157 debugger
= interp
->debugger
;
158 trace_op(interp
, code_start
, code_end
, 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
;
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
);
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.
194 PARROT_WARN_UNUSED_RESULT
195 PARROT_CAN_RETURN_NULL
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
);
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
;
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.
230 PARROT_WARN_UNUSED_RESULT
231 PARROT_CAN_RETURN_NULL
233 runops_gc_debug_core(PARROT_INTERP
, ARGIN(opcode_t
*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
;
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.
263 PARROT_WARN_UNUSED_RESULT
264 PARROT_CAN_RETURN_NULL
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
276 profile
->data
[old_op
].time
+=
277 Parrot_floatval_time() - profile
->starttime
;
280 while (pc
) {/* && pc >= code_start && pc < code_end) */
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();
289 /* profile->cur_op may be different, if exception was thrown */
290 profile
->data
[profile
->cur_op
].time
+=
291 Parrot_floatval_time() - profile
->starttime
;
294 /* old opcode continues */
295 profile
->starttime
= Parrot_floatval_time();
296 profile
->cur_op
= old_op
;
309 * c-file-style: "parrot"
311 * vim: expandtab shiftwidth=4: