2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc/parrotinterpreter.pmc - Parrot Interpreter
11 These are the vtable functions for the ParrotInterpreter base class
14 set P1, P0[.IGLOBALS_*] # access interpreter globals
15 set I0, P0[x] # interpinfo I0, x
16 set I0, P0[-1] # get interpreter flags
17 set P0[-1], x # set flags on interpreter
18 # NOTE: this doesn't restart
28 #include "parrot/parrot.h"
29 #include "parrot/embed.h"
30 #include "parrot/dynext.h"
31 #include "pmc_class.h"
36 clone_interpreter(Parrot_Interp dest, const Parrot_Interp source, INTVAL flags)>
38 Clones the interpreter as specified by the flags.
45 clone_interpreter(Parrot_Interp d, Parrot_Interp s, INTVAL flags)
47 /* we block DOD runs while cloning since C<d> is not yet running */
50 d->scheduler = pmc_new(d, enum_class_Scheduler);
51 d->scheduler = VTABLE_share_ro(d, d->scheduler);
53 if (flags & PARROT_CLONE_RUNOPS)
54 d->run_core = s->run_core;
56 if (flags & PARROT_CLONE_INTERP_FLAGS) {
57 /* XXX setting of IS_THREAD? */
59 d->debug_flags = s->debug_flags;
62 if (flags & PARROT_CLONE_HLL) {
63 /* we'd like to share the HLL data. Give it a PMC_sync structure
64 if it doesn't have one already */
65 add_pmc_sync(s, s->HLL_info);
66 d->HLL_info = s->HLL_info;
67 Parrot_regenerate_HLL_namespaces(d);
70 if (flags & (PARROT_CLONE_LIBRARIES | PARROT_CLONE_CLASSES)) {
71 INTVAL i, last_remove;
72 const INTVAL start = d->n_vtable_max;
74 /* copy type registrations to keep type numbers the same */
75 d->class_hash = Parrot_clone(d, s->class_hash);
76 d->n_vtable_max = s->n_vtable_max;
78 if (d->n_vtable_max > d->n_vtable_alloced)
79 parrot_realloc_vtables(d);
81 last_remove = s->n_vtable_max;
83 for (i = s->n_vtable_max - 1; i >= start; --i) {
84 if (s->vtables[i] && s->vtables[i]->pmc_class &&
85 PObj_is_class_TEST(s->vtables[i]->pmc_class)) {
86 STRING * const class_name =
87 VTABLE_get_string(s, s->vtables[i]->pmc_class);
88 PARROT_ASSERT(VTABLE_exists_keyed_str(d,
89 d->class_hash, class_name));
91 VTABLE_delete_keyed_str(d, d->class_hash, class_name);
93 if (last_remove == i + 1) {
101 if (flags & PARROT_CLONE_LIBRARIES) {
102 PMC * const libs = VTABLE_get_pmc_keyed_int(s, s->iglobals,
104 PMC * const lib_iter = VTABLE_get_iter(s, libs);
105 const INTVAL n = VTABLE_elements(s, libs);
108 for (i = 0; i < n; ++i) {
109 STRING * const key = VTABLE_shift_string(s, lib_iter);
110 PMC * const lib_pmc = VTABLE_get_pmc_keyed_str(s, libs, key);
111 PMC * const ignored = Parrot_clone_lib_into(d, s, lib_pmc);
116 if (flags & PARROT_CLONE_CLASSES) {
118 for (i = 0; i < s->n_vtable_max; ++i) {
119 if (s->vtables[i] && s->vtables[i]->pmc_class &&
120 PObj_is_class_TEST(s->vtables[i]->pmc_class)) {
121 /* Cloning the class into the new interpreter ought
122 * to be sufficient to instantiate the class. */
123 PMC *source = s->vtables[i]->pmc_class;
124 PMC *dest = Parrot_clone(d, source);
125 Parrot_Class *source_class = PARROT_CLASS(source);
126 Parrot_Class *dest_class = PARROT_CLASS(dest);
127 dest_class->name = string_copy(d, source_class->name);
128 dest_class->_namespace = VTABLE_clone(d, source_class->_namespace);
133 if (flags & PARROT_CLONE_CODE)
136 if (flags & PARROT_CLONE_GLOBALS)
137 pt_clone_globals(d, s);
139 Parrot_unblock_DOD(d);
146 create_interp(PMC *self, Parrot_Interp parent)>
148 Creates a new child interpreter of C<parent>.
155 create_interp(PMC *self, Parrot_Interp parent)
157 Interp_flags flag = PARROT_NO_FLAGS;
158 Parrot_Interp new_interp;
160 if (self->vtable->base_type == enum_class_ParrotThread)
161 flag = PARROT_IS_THREAD;
163 new_interp = make_interpreter(parent, flag);
164 PMC_data(self) = new_interp;
166 VTABLE_set_pmc_keyed_int(new_interp, new_interp->iglobals,
167 (INTVAL) IGLOBALS_INTERPRETER, self);
169 new_interp->current_cont = NEED_CONTINUATION;
173 recursion_limit(Parrot_Interp interp, PMC *self, int l)
175 const int ret = interp->recursion_limit;
176 interp->recursion_limit = l;
180 pmclass ParrotInterpreter need_ext no_ro {
190 =item C<void class_init()>
192 Class initialization.
199 const int typ = enum_class_ParrotInterpreter;
202 /* TODO unify and fix signatures */
203 register_nci_method(INTERP, typ,
204 F2DPTR(pt_thread_yield), "yield", "v");
207 register_nci_method(INTERP, typ,
208 F2DPTR(recursion_limit), "recursion_limit", "iJOi");
216 Initializes the interpreter.
224 * init/init_pmc may be called internally (from thread creation in
225 * ParrotThread::init_pmc() or stand-alone
226 * so we check, if the interpreter is already setup
228 if (!PMC_data(SELF)) {
229 create_interp(SELF, INTERP);
230 PARROT_ASSERT(PMC_data(SELF));
233 PMC_struct_val(SELF) = NULL;
234 PMC_pmc_val(SELF) = NULL;
239 =item C<void init_pmc(PMC *parent)>
241 Initializes a child interpreter with C<*parent> if C<parent> is
242 a ParrotInterpreter instance. Otherwise takes the thread ID from
243 C<parent> and uses that thread.
249 VTABLE void init_pmc(PMC *parent) {
250 Parrot_Interp p = PMC_data_typed(parent, Parrot_Interp);
253 create_interp(SELF, p);
255 PMC_struct_val(SELF) = NULL;
260 =item C<void set_pointer(void *value)>
262 Sets C<struct_val> to C<*value>.
268 VTABLE void set_pointer(void *value) {
269 PMC_struct_val(SELF) = value;
274 =item C<void *get_pointer()>
276 Returns C<struct_val>.
282 VTABLE void *get_pointer() {
283 return PMC_struct_val(SELF);
288 =item C<INTVAL get_integer()>
290 Returns the thread id of the interpreter.
296 VTABLE INTVAL get_integer() {
297 const Parrot_Interp i = PMC_data_typed(SELF, Parrot_Interp);
298 return (INTVAL)i->thread_data->tid;
303 =item C<opcode_t *invoke(void *next)>
305 Runs the interpreter's byte code.
311 VTABLE opcode_t *invoke(void *next) {
312 Interp * const new_interp = PMC_data_typed(SELF, Interp *);
315 pt_thread_prepare_for_run(new_interp, interp);
317 /* TODO pass arguments from parent (interp) to child (new_interp) by
318 * possibly clone of share the arguments r/o args can be passed as is */
320 /* calculate offset and run */
321 runops(new_interp, (opcode_t *)PMC_struct_val(SELF) -
322 (opcode_t *)interp->code->base.data);
324 return (opcode_t *)next;
329 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
331 Returns the PMC global value for C<key>.
337 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
338 Interp * const new_interp = PMC_data_typed(SELF, Interp *);
340 if (key >= 0 && key < IGLOBALS_SIZE)
341 return VTABLE_get_pmc_keyed_int(new_interp,
342 new_interp->iglobals, key);
344 /* quick hack to get the global stash */
346 return new_interp->root_namespace;
353 =item C<PMC *get_pmc_keyed(PMC *key)>
355 Introspection interface. C<key> can be:
357 "sub" ... return Sub object of this subroutine
358 "continuation" ... return Continuation PMC
359 "lexpad" ... return lexpad PMC for this sub
360 "namespace" ... return namespace PMC for this sub
361 "outer" ... return outer sub of this closure
362 "<item>"; level ... same for caller <level>
363 "outer"; "<item>" ... same for outer level 1
364 "outer"; "<item>"; level ... same for outer <level>
365 "globals" ... return global stash
371 VTABLE PMC *get_pmc_keyed(PMC *key) {
373 STRING *outer = NULL;
374 STRING *item = key_string(interp, key);
375 STRING *s = CONST_STRING(interp, "globals");
378 parrot_context_t *ctx;
380 if (string_equal(interp, item, s) == 0)
381 return interp->root_namespace;
383 s = CONST_STRING(interp, "outer");
385 if (string_equal(interp, item, s) == 0) {
387 nextkey = key_next(INTERP, key);
389 if (nextkey && (PObj_get_FLAGS(nextkey) & KEY_string_FLAG)) {
391 item = key_string(interp, key);
395 nextkey = key_next(INTERP, key);
398 level = key_integer(interp, nextkey);
403 real_exception(interp, NULL, E_ValueError, "No such caller depth");
405 ctx = CONTEXT(interp);
408 for (; level; --level) {
409 ctx = ctx->outer_ctx;
411 real_exception(interp, NULL, E_ValueError,
412 "No such outer depth");
416 for (; level; --level) {
417 cont = ctx->current_cont;
419 if (PMC_IS_NULL(cont) || !PMC_cont(cont)->seg)
420 real_exception(interp, NULL, E_ValueError,
421 "No such caller depth");
423 ctx = PMC_cont(cont)->to_ctx;
425 if (!ctx->current_sub)
426 real_exception(interp, NULL, E_ValueError,
427 "No such caller depth");
432 return ctx->current_sub;
434 s = CONST_STRING(interp, "sub");
436 if (string_equal(interp, item, s) == 0)
437 return ctx->current_sub;
439 s = CONST_STRING(interp, "lexpad");
441 if (string_equal(interp, item, s) == 0)
444 s = CONST_STRING(interp, "namespace");
446 if (string_equal(interp, item, s) == 0)
447 return ctx->current_namespace;
449 s = CONST_STRING(interp, "continuation");
451 if (string_equal(interp, item, s) == 0)
452 return VTABLE_clone(interp, ctx->current_cont);
454 real_exception(interp, NULL, E_ValueError,
455 "No such item %Ss", item);
460 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
462 Returns the interpreter info for C<key>.
468 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
469 Interp * const new_interp = PMC_data_typed(SELF, Interp *);
472 return (INTVAL)new_interp->flags;
474 return interpinfo(new_interp, key);
479 =item C<void set_integer_keyed_int(INTVAL key, INTVAL val)>
481 Sets the interpreter info for C<key> to C<val>.
487 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL val) {
488 Interp * const new_interp = PMC_data_typed(SELF, Interp *);
490 /* set interpreter flags */
492 const INTVAL allowed = PARROT_BOUNDS_FLAG | PARROT_PROFILE_FLAG |
493 PARROT_GC_DEBUG_FLAG;
494 Parrot_clear_flag(new_interp, allowed);
495 Parrot_set_flag(new_interp, val & allowed);
501 =item C<PMC *clone()>
503 First attempt to make things running, and to see, where problems may
504 arise. Only minimal items are done yet.
506 XXX this should of course call C<Parrot_clone()> and use freeze/thaw.
512 VTABLE PMC *clone() {
513 PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type);
515 clone_interpreter((Parrot_Interp)PMC_data(dest),
516 (Parrot_Interp)PMC_data(SELF), PARROT_CLONE_DEFAULT);
523 =item C<INTVAL is_equal(PMC *val)>
525 Returns whether the interpreter is equal to C<*val>.
527 Two interpreters (threads) are equal if both are non-threaded or they
528 have the same thread id.
534 VTABLE INTVAL is_equal(PMC *val) {
535 Parrot_Interp self = PMC_data_typed(SELF, Parrot_Interp);
536 Parrot_Interp other = PMC_data_typed(val, Parrot_Interp);
538 if (!self->thread_data && !other->thread_data)
541 if (self->thread_data && other->thread_data &&
542 self->thread_data->tid == other->thread_data->tid)
550 =item C<void visit(visit_info *info)>
552 This is used by freeze/thaw to visit the contents of the interpreter.
554 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
556 =item C<void freeze(visit_info *info)>
558 Used to archive the interpreter. Actually not the whole interpreter is
559 frozen but the state of the interpreter, which includes everything that
560 has changes since creating an empty interpreter.
562 =item C<void thaw(visit_info *info)>
564 Used to unarchive the interpreter. This merges the changes into this
565 interpreter instance.
567 =item C<void thawfinish(visit_info *info)>
575 VTABLE void visit(visit_info *info) {
578 * the information frozen here is part of all PBCs
579 * we probably need to freeze all dynamic extensible
580 * mappings (or at least the dynamic part)
582 * charsets idx - name
583 * encodings idx - name
584 * pmc types idx - name
585 * dynamic oplibs opcode nr - opname
587 * The machine thawing this info still needs to load
588 * these extensions, but the order of loading could be
591 * creating all these info as standard PMCs would vastly
592 * simplify this process
594 * thaw would then need a merge operation:
595 * - compare existing for sanity
600 if (info->what == VISIT_THAW_NORMAL ||
601 info->what == VISIT_THAW_CONSTANTS) {
602 pos = &PMC_pmc_val(SELF);
605 pos = &INTERP->HLL_info;
607 info->thaw_ptr = pos;
608 (info->visit_pmc_now)(INTERP, *pos, info);
611 VTABLE void thaw(visit_info *info) {
612 if (info->extra_flags == EXTRA_IS_PROP_HASH) {
615 else if (info->extra_flags == EXTRA_IS_NULL) {
616 PMC_data(SELF) = INTERP;
617 info->what = VISIT_THAW_CONSTANTS;
621 void thawfinish(visit_info *info) {
622 PMC * const new_info = PMC_pmc_val(SELF);
623 const INTVAL m = VTABLE_elements(INTERP, new_info);
626 PMC_pmc_val(SELF) = NULL;
629 /* TODO compare old entries */
631 for (i = 0; i < m; ++i) {
632 PMC * const entry = VTABLE_get_pmc_keyed_int(INTERP, new_info, i);
633 PMC * const lib_pmc = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_lib);
634 PMC * const name_pmc = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_name);
635 PMC * const typemap = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_typemap);
638 if (!PMC_IS_NULL(name_pmc)) {
639 STRING * const hll_name = VTABLE_get_string(INTERP, name_pmc);
641 hll_id = Parrot_register_HLL(INTERP, hll_name);
644 if (!PMC_IS_NULL(lib_pmc)) {
645 STRING *lib_name = VTABLE_get_string(INTERP, lib_pmc);
648 if (!STRING_IS_EMPTY(lib_name)) {
650 ignored = Parrot_load_lib(INTERP, lib_name, NULL);
651 id = Parrot_register_HLL_lib(INTERP, lib_name);
658 if (hll_id >= 0 && !PMC_IS_NULL(typemap)) {
659 PMC *iter = VTABLE_get_iter(INTERP, typemap);
660 INTVAL e = VTABLE_get_integer(INTERP, typemap);
663 for (i = 0; i < e; ++i) {
664 PMC * const key = VTABLE_shift_pmc(INTERP, iter);
665 const INTVAL core_type = VTABLE_get_integer(INTERP, key);
666 const INTVAL hll_type =
667 VTABLE_get_integer_keyed_int(INTERP, typemap, core_type);
669 Parrot_register_HLL_type(INTERP, hll_id,
670 core_type, hll_type);
677 Parrot_do_dod_run(PMC_data_typed(SELF, Parrot_Interp), 0);
691 * c-file-style: "parrot"
693 * vim: expandtab shiftwidth=4: