fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / runcore / main.c
blob44dd0d7a4334f28969817f863144eff024e1a0ba
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/runcore/main.c - main functions for Parrot runcores
9 =head1 DESCRIPTION
11 The runcore API handles running the operations.
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/runcore_api.h"
23 #include "parrot/runcore_profiling.h"
24 #include "parrot/oplib/core_ops.h"
25 #include "parrot/oplib/ops.h"
26 #include "main.str"
28 #include "parrot/dynext.h"
29 #include "pmc/pmc_parrotlibrary.h"
30 #include "pmc/pmc_callcontext.h"
33 /* HEADERIZER HFILE: include/parrot/runcore_api.h */
34 /* XXX Needs to get done at the same time as the other interpreter files */
36 /* HEADERIZER BEGIN: static */
37 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
39 PARROT_WARN_UNUSED_RESULT
40 PARROT_CANNOT_RETURN_NULL
41 static oplib_init_f get_dynamic_op_lib_init(SHIM_INTERP,
42 ARGIN(const PMC *lib))
43 __attribute__nonnull__(2);
45 #define ASSERT_ARGS_get_dynamic_op_lib_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
46 PARROT_ASSERT_ARG(lib))
47 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
48 /* HEADERIZER END: static */
52 =item C<void Parrot_runcore_init(PARROT_INTERP)>
54 Initializes the runcores.
56 =cut
60 void
61 Parrot_runcore_init(PARROT_INTERP)
63 ASSERT_ARGS(Parrot_runcore_init)
64 STRING * const default_core = CONST_STRING(interp, "fast");
66 interp->cores = NULL;
67 interp->num_cores = 0;
69 Parrot_runcore_slow_init(interp);
70 Parrot_runcore_fast_init(interp);
72 Parrot_runcore_exec_init(interp);
73 Parrot_runcore_gc_debug_init(interp);
74 Parrot_runcore_debugger_init(interp);
76 Parrot_runcore_profiling_init(interp);
78 /* set the default runcore */
79 Parrot_runcore_switch(interp, default_core);
85 =item C<INTVAL Parrot_runcore_register(PARROT_INTERP, Parrot_runcore_t
86 *coredata)>
88 Registers a new runcore with Parrot. Returns 1 on success, 0 on failure.
90 =cut
94 PARROT_EXPORT
95 INTVAL
96 Parrot_runcore_register(PARROT_INTERP, ARGIN(Parrot_runcore_t *coredata))
98 ASSERT_ARGS(Parrot_runcore_register)
99 size_t i = interp->num_cores++;
101 interp->cores = mem_gc_realloc_n_typed_zeroed(interp, interp->cores,
102 interp->num_cores, i, Parrot_runcore_t *);
104 interp->cores[i] = coredata;
106 return 1;
112 =item C<void Parrot_runcore_switch(PARROT_INTERP, STRING *name)>
114 Switches to a named runcore. Throws an exception on an unknown runcore.
116 =cut
120 PARROT_EXPORT
121 void
122 Parrot_runcore_switch(PARROT_INTERP, ARGIN(STRING *name))
124 ASSERT_ARGS(Parrot_runcore_switch)
126 size_t num_cores = interp->num_cores;
127 size_t i;
129 if (interp->run_core
130 && Parrot_str_equal(interp, name, interp->run_core->name))
131 return;
133 for (i = 0; i < num_cores; ++i) {
134 if (Parrot_str_equal(interp, name, interp->cores[i]->name)) {
135 interp->run_core = interp->cores[i];
136 return;
140 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
141 "Invalid runcore %Ss requested\n", name);
147 =item C<static oplib_init_f get_dynamic_op_lib_init(PARROT_INTERP, const PMC
148 *lib)>
150 Returns an dynamic oplib's opcode's library C<op_lib> init function.
152 C<lib> will be a C<ParrotLibrary> PMC.
154 =cut
158 PARROT_WARN_UNUSED_RESULT
159 PARROT_CANNOT_RETURN_NULL
160 static oplib_init_f
161 get_dynamic_op_lib_init(SHIM_INTERP, ARGIN(const PMC *lib))
163 ASSERT_ARGS(get_dynamic_op_lib_init)
164 return (oplib_init_f)D2FPTR(
165 ((Parrot_ParrotLibrary_attributes *)PMC_data(lib))->oplib_init);
171 =item C<void prepare_for_run(PARROT_INTERP)>
173 Prepares to run the interpreter's run core.
175 =cut
179 void
180 prepare_for_run(PARROT_INTERP)
182 ASSERT_ARGS(prepare_for_run)
183 const runcore_prepare_fn_type prepare_run = interp->run_core->prepare_run;
185 if (prepare_run)
186 (*prepare_run)(interp, interp->run_core);
192 =item C<void runops_int(PARROT_INTERP, size_t offset)>
194 Run Parrot operations of loaded code segment until an end opcode is
195 reached. Run core is selected depending on the C<Interp_flags>. When a
196 C<restart> opcode is encountered, a different core may be selected and
197 evaluation of opcode continues.
199 =cut
203 void
204 runops_int(PARROT_INTERP, size_t offset)
206 ASSERT_ARGS(runops_int)
208 interp->resume_offset = offset;
209 interp->resume_flag |= RESUME_RESTART;
211 while (interp->resume_flag & RESUME_RESTART) {
212 opcode_t * const pc = (opcode_t *)
213 interp->code->base.data + interp->resume_offset;
214 const runcore_runops_fn_type core = interp->run_core->runops;
216 interp->resume_offset = 0;
217 interp->resume_flag &= ~(RESUME_RESTART | RESUME_INITIAL);
219 (*core)(interp, interp->run_core, pc);
221 /* if we have fallen out with resume and we were running CGOTO, set
222 * the stacktop again to a sane value, so that restarting the runloop
223 * is ok. */
224 if (interp->resume_flag & RESUME_RESTART) {
225 if ((int)interp->resume_offset < 0)
226 Parrot_ex_throw_from_c_args(interp, NULL, 1,
227 "branch_cs: illegal resume offset");
235 =item C<void Parrot_runcore_destroy(PARROT_INTERP)>
237 Shuts down the runcores and deallocates any dynops memory.
239 =cut
243 void
244 Parrot_runcore_destroy(PARROT_INTERP)
246 ASSERT_ARGS(Parrot_runcore_destroy)
247 size_t num_cores = interp->num_cores;
248 size_t i;
250 for (i = 0; i < num_cores; ++i) {
251 Parrot_runcore_t * const core = interp->cores[i];
252 const runcore_destroy_fn_type destroy = core->destroy;
254 if (destroy)
255 (*destroy)(interp, core);
257 mem_gc_free(interp, core);
260 if (interp->cores)
261 mem_gc_free(interp, interp->cores);
263 interp->cores = NULL;
264 interp->run_core = NULL;
266 if (interp->all_op_libs)
267 mem_gc_free(interp, interp->all_op_libs);
269 interp->all_op_libs = NULL;
275 =back
277 =head2 Dynamic Loading Functions
279 =over 4
281 =item C<void dynop_register(PARROT_INTERP, PMC *lib_pmc)>
283 Register a dynamic oplib.
285 =cut
289 PARROT_EXPORT
290 void
291 dynop_register(PARROT_INTERP, ARGIN(PMC *lib_pmc))
293 ASSERT_ARGS(dynop_register)
294 op_lib_t *lib;
295 oplib_init_f init_func;
297 if (n_interpreters > 1) {
298 /* This is not supported yet because interp->all_op_libs
299 * and interp->op_hash are shared.
301 Parrot_ex_throw_from_c_args(interp, NULL, 1, "loading a new dynoplib while "
302 "more than one thread is running is not supported.");
305 if (!interp->all_op_libs)
306 interp->all_op_libs = mem_gc_allocate_n_zeroed_typed(interp,
307 interp->n_libs + 1, op_lib_t*);
308 else
309 interp->all_op_libs = mem_gc_realloc_n_typed_zeroed(interp, interp->all_op_libs,
310 interp->n_libs + 1, interp->n_libs, op_lib_t *);
312 init_func = get_dynamic_op_lib_init(interp, lib_pmc);
313 lib = init_func(interp, 1);
315 interp->all_op_libs[interp->n_libs++] = lib;
317 /* if we are registering an op_lib variant, called from below the base
318 * names of this lib and the previous one are the same */
319 if (interp->n_libs >= 2
320 && (STREQ(interp->all_op_libs[interp->n_libs-2]->name, lib->name)))
321 return;
323 parrot_hash_oplib(interp, lib);
329 =item C<void parrot_hash_oplib(PARROT_INTERP, op_lib_t *lib)>
331 Add the ops in C<lib> to the global name => op_info hash.
333 =cut
337 void
338 parrot_hash_oplib(PARROT_INTERP, ARGIN(op_lib_t *lib))
340 ASSERT_ARGS(parrot_hash_oplib)
341 int i;
342 for (i = 0; i < lib->op_count; i++) {
343 op_info_t *op = &lib->op_info_table[i];
344 parrot_hash_put(interp, interp->op_hash, (void *)op->full_name, (void *)op);
345 if (!parrot_hash_exists(interp, interp->op_hash, (void *)op->name))
346 parrot_hash_put(interp, interp->op_hash, (void *)op->name, (void *)op);
353 =item C<void disable_event_checking(PARROT_INTERP)>
355 Restore old function table.
357 XXX This is only implemented for the function core at present.
359 =cut
363 PARROT_EXPORT
364 void
365 disable_event_checking(PARROT_INTERP)
367 ASSERT_ARGS(disable_event_checking)
368 PackFile_ByteCode *cs = interp->code;
369 /* restore func table */
370 PARROT_ASSERT(cs->save_func_table);
371 cs->op_func_table = cs->save_func_table;
372 cs->save_func_table = NULL;
378 =item C<void enable_event_checking(PARROT_INTERP)>
380 Replace func table with one that does event checking for all opcodes.
382 NOTE: C<enable_event_checking()> is called async by the event handler
383 thread. All action done from here has to be async safe.
385 XXX This is only implemented for the function core at present.
387 =cut
391 PARROT_EXPORT
392 void
393 enable_event_checking(PARROT_INTERP)
395 ASSERT_ARGS(enable_event_checking)
396 PackFile_ByteCode *cs = interp->code;
398 /* only save if we're not already event checking */
399 if (cs->save_func_table == NULL)
400 cs->save_func_table = cs->op_func_table;
402 /* ensure event checking table is big enough */
403 if (interp->evc_func_table_size < cs->op_count) {
404 int i;
405 op_lib_t *core_lib = get_core_op_lib_init(interp, interp->run_core)(interp, 1);
407 interp->evc_func_table = interp->evc_func_table ?
408 mem_gc_realloc_n_typed_zeroed(interp,
409 interp->evc_func_table, cs->op_count,
410 interp->evc_func_table_size, op_func_t) :
411 mem_gc_allocate_n_zeroed_typed(interp,
412 cs->op_count, op_func_t);
414 for (i = interp->evc_func_table_size; i < cs->op_count; i++)
415 interp->evc_func_table[i] = (op_func_t)
416 D2FPTR(((void**)core_lib->op_func_table)[CORE_OPS_check_events__]);
418 interp->evc_func_table_size = cs->op_count;
421 /* put evc table in place */
422 cs->op_func_table = interp->evc_func_table;
428 =back
430 =head1 SEE ALSO
432 F<include/parrot/interpreter.h>, F<src/interp/inter_cb.c>,
433 F<src/interp/inter_create.c>, F<src/interp/inter_misc.c>, F<src/call/ops.c>.
435 =cut
441 * Local variables:
442 * c-file-style: "parrot"
443 * End:
444 * vim: expandtab shiftwidth=4: