1 /*
2 Copyright (C) 2001-2015, Parrot Foundation.
3
4 =head1 NAME
5
6 src/runcore/main.c - main functions for Parrot runcores
7
8 =head1 DESCRIPTION
9
10 The runcore API handles running the operations.
11
12 =head2 Functions
13
14 =over 4
15
16 =cut
17
18 */
19
20 #include "parrot/parrot.h"
21 #include "parrot/runcore_api.h"
22 #include "parrot/runcore_profiling.h"
23 #include "parrot/runcore_subprof.h"
24 #include "parrot/oplib/core_ops.h"
25 #include "parrot/oplib/ops.h"
26 #include "main.str"
27
28 #include "parrot/dynext.h"
29 #include "pmc/pmc_parrotlibrary.h"
30 #include "pmc/pmc_callcontext.h"
31
32
33 /* HEADERIZER HFILE: include/parrot/runcore_api.h */
34 /* XXX Needs to get done at the same time as the other interpreter files */
35
36 /* HEADERIZER BEGIN: static */
37 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
38
39 PARROT_WARN_UNUSED_RESULT
40 PARROT_CANNOT_RETURN_NULL
41 static oplib_init_f get_dynamic_op_lib_init(PARROT_INTERP,
42 ARGIN(const PMC *lib))
43 __attribute__nonnull__(2);
44
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 */
49
50 /*
51
52 =item C<void Parrot_runcore_init(PARROT_INTERP)>
53
54 Initializes the runcores.
55
56 =cut
57
58 */
59
60 void
Parrot_runcore_init(PARROT_INTERP)61 Parrot_runcore_init(PARROT_INTERP)
62 {
63 ASSERT_ARGS(Parrot_runcore_init)
64 STRING * const default_core = CONST_STRING(interp, "fast");
65
66 interp->cores = NULL;
67 interp->num_cores = 0;
68
69 Parrot_runcore_slow_init(interp);
70 Parrot_runcore_fast_init(interp);
71
72 Parrot_runcore_subprof_init(interp);
73 /* Parrot_runcore_exec_init(interp); */
74 Parrot_runcore_gc_debug_init(interp);
75 Parrot_runcore_debugger_init(interp);
76
77 Parrot_runcore_profiling_init(interp);
78
79 /* set the default runcore */
80 Parrot_runcore_switch(interp, default_core);
81 }
82
83
84 /*
85
86 =item C<INTVAL Parrot_runcore_register(PARROT_INTERP, Parrot_runcore_t
87 *coredata)>
88
89 Registers a new runcore with Parrot. Returns 1 on success, 0 on failure.
90
91 =cut
92
93 */
94
95 PARROT_EXPORT
96 INTVAL
Parrot_runcore_register(PARROT_INTERP,ARGIN (Parrot_runcore_t * coredata))97 Parrot_runcore_register(PARROT_INTERP, ARGIN(Parrot_runcore_t *coredata))
98 {
99 ASSERT_ARGS(Parrot_runcore_register)
100 size_t i = interp->num_cores++;
101
102 interp->cores = mem_gc_realloc_n_typed_zeroed(interp, interp->cores,
103 interp->num_cores, i, Parrot_runcore_t *);
104
105 interp->cores[i] = coredata;
106
107 return 1;
108 }
109
110
111 /*
112
113 =item C<void Parrot_runcore_switch(PARROT_INTERP, STRING *name)>
114
115 Switches to a named runcore. Throws an exception on an unknown runcore.
116
117 =cut
118
119 */
120
121 PARROT_EXPORT
122 void
Parrot_runcore_switch(PARROT_INTERP,ARGIN (STRING * name))123 Parrot_runcore_switch(PARROT_INTERP, ARGIN(STRING *name))
124 {
125 ASSERT_ARGS(Parrot_runcore_switch)
126
127 size_t num_cores = interp->num_cores;
128 size_t i;
129
130 if (interp->run_core
131 && STRING_equal(interp, name, interp->run_core->name))
132 return;
133
134 for (i = 0; i < num_cores; ++i) {
135 if (STRING_equal(interp, name, interp->cores[i]->name)) {
136 interp->run_core = interp->cores[i];
137 return;
138 }
139 }
140
141 /* XXX This might end in an endless exception cycle. Better panic here? */
142 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
143 "Invalid runcore %Ss requested", name);
144 }
145
146
147 /*
148
149 =item C<static oplib_init_f get_dynamic_op_lib_init(PARROT_INTERP, const PMC
150 *lib)>
151
152 Returns an dynamic oplib's opcode's library C<op_lib> init function.
153
154 C<lib> will be a C<ParrotLibrary> PMC.
155
156 =cut
157
158 */
159
160 PARROT_WARN_UNUSED_RESULT
161 PARROT_CANNOT_RETURN_NULL
162 static oplib_init_f
get_dynamic_op_lib_init(SHIM_INTERP,ARGIN (const PMC * lib))163 get_dynamic_op_lib_init(SHIM_INTERP, ARGIN(const PMC *lib))
164 {
165 ASSERT_ARGS(get_dynamic_op_lib_init)
166 return (oplib_init_f)D2FPTR(
167 ((Parrot_ParrotLibrary_attributes *)PMC_data(lib))->oplib_init);
168 }
169
170
171 /*
172
173 =item C<void prepare_for_run(PARROT_INTERP)>
174
175 Prepares to run the interpreter's run core.
176
177 =cut
178
179 */
180
181 void
prepare_for_run(PARROT_INTERP)182 prepare_for_run(PARROT_INTERP)
183 {
184 ASSERT_ARGS(prepare_for_run)
185 const runcore_prepare_fn_type prepare_run = interp->run_core->prepare_run;
186
187 if (prepare_run)
188 (*prepare_run)(interp, interp->run_core);
189 }
190
191
192 /*
193
194 =item C<void runops_int(PARROT_INTERP, size_t offset)>
195
196 Run Parrot operations of loaded code segment until an end opcode is
197 reached. Run core is selected depending on the C<Interp_flags>. When a
198 C<restart> opcode is encountered, a different core may be selected and
199 evaluation of opcode continues.
200
201 =cut
202
203 */
204
205 void
runops_int(PARROT_INTERP,size_t offset)206 runops_int(PARROT_INTERP, size_t offset)
207 {
208 ASSERT_ARGS(runops_int)
209
210 interp->resume_offset = offset;
211 interp->resume_flag |= RESUME_RESTART;
212
213 while (interp->resume_flag & RESUME_RESTART) {
214 opcode_t * const pc = interp->code->base.data + interp->resume_offset;
215 const runcore_runops_fn_type core = interp->run_core->runops;
216
217 interp->resume_offset = 0;
218 interp->resume_flag &= ~(RESUME_RESTART | RESUME_INITIAL);
219
220 (*core)(interp, interp->run_core, pc);
221
222 /* if we have fallen out with resume and we were running CGOTO, set
223 * the stacktop again to a sane value, so that restarting the runloop
224 * is ok. */
225 if (interp->resume_flag & RESUME_RESTART) {
226 if ((int)interp->resume_offset < 0)
227 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_INTERNAL_PANIC,
228 "branch_cs: illegal resume offset");
229 }
230 }
231 }
232
233
234 /*
235
236 =item C<void Parrot_runcore_destroy(PARROT_INTERP)>
237
238 Shuts down the runcores and deallocates any dynops memory.
239
240 =cut
241
242 */
243
244 void
Parrot_runcore_destroy(PARROT_INTERP)245 Parrot_runcore_destroy(PARROT_INTERP)
246 {
247 ASSERT_ARGS(Parrot_runcore_destroy)
248 size_t num_cores = interp->num_cores;
249 size_t i;
250
251 for (i = 0; i < num_cores; ++i) {
252 Parrot_runcore_t * const core = interp->cores[i];
253 const runcore_destroy_fn_type destroy = core->destroy;
254
255 if (destroy)
256 (*destroy)(interp, core);
257
258 mem_gc_free(interp, core);
259 }
260
261 if (interp->cores)
262 mem_gc_free(interp, interp->cores);
263
264 interp->cores = NULL;
265 interp->run_core = NULL;
266
267 if (interp->all_op_libs)
268 mem_gc_free(interp, interp->all_op_libs);
269
270 interp->all_op_libs = NULL;
271 }
272
273
274 /*
275
276 =back
277
278 =head2 Dynamic Loading Functions
279
280 =over 4
281
282 =item C<void Parrot_dynop_register(PARROT_INTERP, PMC *lib_pmc)>
283
284 Register a dynamic oplib.
285
286 =cut
287
288 */
289
290 PARROT_EXPORT
291 void
Parrot_dynop_register(PARROT_INTERP,ARGIN (PMC * lib_pmc))292 Parrot_dynop_register(PARROT_INTERP, ARGIN(PMC *lib_pmc))
293 {
294 ASSERT_ARGS(Parrot_dynop_register)
295 op_lib_t *lib;
296 oplib_init_f init_func;
297
298 if (!interp->all_op_libs)
299 interp->all_op_libs = mem_gc_allocate_n_zeroed_typed(interp,
300 interp->n_libs + 1, op_lib_t*);
301 else
302 interp->all_op_libs = mem_gc_realloc_n_typed_zeroed(interp, interp->all_op_libs,
303 interp->n_libs + 1, interp->n_libs, op_lib_t *);
304
305 init_func = get_dynamic_op_lib_init(interp, lib_pmc);
306 lib = init_func(interp, 1);
307
308 interp->all_op_libs[interp->n_libs++] = lib;
309
310 /* if we are registering an op_lib variant, called from below the base
311 * names of this lib and the previous one are the same */
312 if (interp->n_libs >= 2
313 && (STREQ(interp->all_op_libs[interp->n_libs-2]->name, lib->name)))
314 return;
315
316 parrot_hash_oplib(interp, lib);
317 }
318
319 /*
320
321 =item C<void dynop_register(PARROT_INTERP, PMC *lib_pmc)>
322
323 This function is deprecated, use C<Parrot_dynop_register> instead.
324
325 =cut
326
327 */
328
329 PARROT_EXPORT
330 PARROT_DEPRECATED
331 void
dynop_register(PARROT_INTERP,ARGIN (PMC * lib_pmc))332 dynop_register(PARROT_INTERP, ARGIN(PMC *lib_pmc))
333 {
334 ASSERT_ARGS(dynop_register)
335 Parrot_dynop_register(interp, lib_pmc);
336 }
337
338 /*
339
340 =item C<void parrot_hash_oplib(PARROT_INTERP, op_lib_t *lib)>
341
342 Add the ops in C<lib> to the global name => op_info hash.
343
344 =cut
345
346 */
347
348 void
parrot_hash_oplib(PARROT_INTERP,ARGIN (op_lib_t * lib))349 parrot_hash_oplib(PARROT_INTERP, ARGIN(op_lib_t *lib))
350 {
351 ASSERT_ARGS(parrot_hash_oplib)
352
353 int i;
354
355 DECL_CONST_CAST;
356
357 for (i = 0; i < lib->op_count; i++) {
358 op_info_t *op = &lib->op_info_table[i];
359 Parrot_hash_put(interp, interp->op_hash, PARROT_const_cast(char *, op->full_name),
360 (void *)op);
361
362 if (!Parrot_hash_exists(interp, interp->op_hash, PARROT_const_cast(char *, op->name)))
363 Parrot_hash_put(interp, interp->op_hash, PARROT_const_cast(char *, op->name),
364 (void *)op);
365 }
366 }
367
368
369 /*
370
371 =item C<void Parrot_runcore_disable_event_checking(PARROT_INTERP)>
372
373 Restore old function table.
374
375 XXX This is only implemented for the function core at present.
376
377 =cut
378
379 */
380
381 PARROT_EXPORT
382 void
Parrot_runcore_disable_event_checking(PARROT_INTERP)383 Parrot_runcore_disable_event_checking(PARROT_INTERP)
384 {
385 ASSERT_ARGS(Parrot_runcore_disable_event_checking)
386 PackFile_ByteCode *cs = interp->code;
387 /* restore func table */
388 PARROT_ASSERT(cs->save_func_table);
389 cs->op_func_table = cs->save_func_table;
390 cs->save_func_table = NULL;
391 }
392
393
394 /*
395
396 =item C<void Parrot_runcore_enable_event_checking(PARROT_INTERP)>
397
398 Replace func table with one that does event checking for all opcodes.
399
400 NOTE: C<enable_event_checking()> is called async by the event handler
401 thread. All action done from here has to be async safe.
402
403 XXX This is only implemented for the function core at present.
404
405 =cut
406
407 */
408
409 PARROT_EXPORT
410 void
Parrot_runcore_enable_event_checking(PARROT_INTERP)411 Parrot_runcore_enable_event_checking(PARROT_INTERP)
412 {
413 ASSERT_ARGS(Parrot_runcore_enable_event_checking)
414 PackFile_ByteCode *cs = interp->code;
415
416 /* only save if we're not already event checking */
417 if (cs->save_func_table == NULL)
418 cs->save_func_table = cs->op_func_table;
419
420 /* ensure event checking table is big enough */
421 if (interp->evc_func_table_size < cs->op_count) {
422 size_t i;
423 op_lib_t *core_lib = get_core_op_lib_init(interp, interp->run_core)(interp, 1);
424
425 interp->evc_func_table = interp->evc_func_table ?
426 mem_gc_realloc_n_typed_zeroed(interp,
427 interp->evc_func_table, cs->op_count,
428 interp->evc_func_table_size, op_func_t) :
429 mem_gc_allocate_n_zeroed_typed(interp,
430 cs->op_count, op_func_t);
431
432 for (i = interp->evc_func_table_size; i < cs->op_count; i++)
433 interp->evc_func_table[i] =
434 core_lib->op_func_table[PARROT_OP_check_events__];
435
436 interp->evc_func_table_size = cs->op_count;
437 }
438
439 /* put evc table in place */
440 cs->op_func_table = interp->evc_func_table;
441 }
442
443
444 /*
445
446 =back
447
448 =head1 SEE ALSO
449
450 F<include/parrot/interpreter.h>, F<src/interp/inter_cb.c>,
451 F<src/interp/inter_create.c>, F<src/interp/inter_misc.c>, F<src/call/ops.c>.
452
453 =cut
454
455 */
456
457
458 /*
459 * Local variables:
460 * c-file-style: "parrot"
461 * End:
462 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
463 */
464