2 Copyright (C) 2001-2010, Parrot 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/embed.h"
29 #include "parrot/dynext.h"
30 #include "parrot/io.h"
31 #include "parrot/runcore_api.h"
32 #include "pmc/pmc_class.h"
33 #include "pmc/pmc_sub.h"
35 #define PMC_interp(x) ((Parrot_ParrotInterpreter_attributes *)PMC_data(x))->interp
36 #define PMC_args(x) ((Parrot_ParrotInterpreter_attributes *)PMC_data(x))->args
37 #define PMC_sub(x) ((Parrot_ParrotInterpreter_attributes *)PMC_data(x))->sub
39 /* HEADERIZER HFILE: none */
40 /* HEADERIZER BEGIN: static */
41 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
43 static void create_interp(
45 ARGIN_NULLOK(Parrot_Interp parent))
46 __attribute__nonnull__(1);
48 #define ASSERT_ARGS_create_interp __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
49 PARROT_ASSERT_ARG(self))
50 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
51 /* HEADERIZER END: static */
55 =item C<void clone_interpreter(Parrot_Interp d, Parrot_Interp s, INTVAL flags)>
57 Clones the interpreter as specified by the flags.
64 clone_interpreter(Parrot_Interp d, Parrot_Interp s, INTVAL flags)
66 /* we block GC runs while cloning since C<d> is not yet running */
67 Parrot_block_GC_mark(d);
69 d->scheduler = Parrot_pmc_new(d, enum_class_Scheduler);
70 d->scheduler = VTABLE_share_ro(d, d->scheduler);
72 /* can't copy directly, unless you want double-frees */
73 if (flags & PARROT_CLONE_RUNOPS)
74 Parrot_runcore_switch(d, s->run_core->name);
76 if (flags & PARROT_CLONE_INTERP_FLAGS) {
77 /* XXX setting of IS_THREAD? */
79 d->debug_flags = s->debug_flags;
82 if (flags & PARROT_CLONE_HLL) {
83 /* we'd like to share the HLL data. Give it a PMC_sync structure
84 if it doesn't have one already */
85 d->HLL_info = s->HLL_info;
86 Parrot_regenerate_HLL_namespaces(d);
89 if (flags & (PARROT_CLONE_LIBRARIES | PARROT_CLONE_CLASSES)) {
90 INTVAL i, last_remove;
91 const INTVAL start = d->n_vtable_max;
93 /* copy type registrations to keep type numbers the same */
94 d->class_hash = Parrot_clone(d, s->class_hash);
95 d->n_vtable_max = s->n_vtable_max;
97 if (d->n_vtable_max > d->n_vtable_alloced)
98 parrot_realloc_vtables(d);
100 last_remove = s->n_vtable_max;
102 for (i = s->n_vtable_max - 1; i >= start; --i) {
103 if (s->vtables[i] && s->vtables[i]->pmc_class &&
104 PObj_is_class_TEST(s->vtables[i]->pmc_class)) {
105 STRING * const class_name =
106 VTABLE_get_string(s, s->vtables[i]->pmc_class);
107 PARROT_ASSERT(VTABLE_exists_keyed_str(d,
108 d->class_hash, class_name));
110 VTABLE_delete_keyed_str(d, d->class_hash, class_name);
112 if (last_remove == i + 1) {
120 if (flags & PARROT_CLONE_LIBRARIES) {
121 PMC * const libs = VTABLE_get_pmc_keyed_int(s, s->iglobals,
123 PMC * const lib_iter = VTABLE_get_iter(s, libs);
124 const INTVAL n = VTABLE_elements(s, libs);
127 for (i = 0; i < n; ++i) {
128 STRING * const key = VTABLE_shift_string(s, lib_iter);
129 PMC * const lib_pmc = VTABLE_get_pmc_keyed_str(s, libs, key);
130 PMC * const ignored = Parrot_clone_lib_into(d, s, lib_pmc);
135 if (flags & PARROT_CLONE_CLASSES) {
137 for (i = 0; i < s->n_vtable_max; ++i) {
138 if (s->vtables[i] && s->vtables[i]->pmc_class &&
139 PObj_is_class_TEST(s->vtables[i]->pmc_class)) {
140 /* Cloning the class into the new interpreter ought
141 * to be sufficient to instantiate the class. */
142 PMC * const source = s->vtables[i]->pmc_class;
143 PMC * const dest = Parrot_clone(d, source);
144 Parrot_Class_attributes * const source_class = PARROT_CLASS(source);
145 Parrot_Class_attributes * const dest_class = PARROT_CLASS(dest);
147 dest_class->name = source_class->name;
148 dest_class->_namespace = VTABLE_clone(d, source_class->_namespace);
153 if (flags & PARROT_CLONE_CODE)
156 if (flags & PARROT_CLONE_GLOBALS)
157 pt_clone_globals(d, s);
159 Parrot_unblock_GC_mark(d);
165 =item C<static void create_interp(PMC *self, Parrot_Interp parent)>
167 Creates a new child interpreter of C<parent>.
174 create_interp(ARGIN(PMC *self), ARGIN_NULLOK(Parrot_Interp parent))
176 ASSERT_ARGS(create_interp)
177 Interp_flags flag = PARROT_NO_FLAGS;
178 Parrot_Interp new_interp;
180 if (self->vtable->base_type == enum_class_ParrotThread)
181 flag = PARROT_IS_THREAD;
183 new_interp = make_interpreter(parent, (INTVAL)flag);
184 PMC_interp(self) = new_interp;
186 VTABLE_set_pmc_keyed_int(new_interp, new_interp->iglobals,
187 (INTVAL) IGLOBALS_INTERPRETER, self);
189 new_interp->current_cont = NEED_CONTINUATION;
192 pmclass ParrotInterpreter no_ro manual_attrs provides invokable {
193 ATTR struct parrot_interp_t *interp; /* this PMC's interpreter */
194 ATTR INTVAL tid; /* thread id */
195 ATTR PMC *args; /* args passed to this thread */
196 ATTR PMC *sub; /* this thread's sub */
208 Yield the current thread
210 =item C<recursion_limit(INTVAL l :optional, INTVAL has_l :opt_flag )>
212 Gets the recursion limit of the interpreter, optionally setting it to something
223 METHOD recursion_limit(INTVAL l :optional, INTVAL has_l :opt_flag) {
224 const INTVAL ret = INTERP->recursion_limit;
226 INTERP->recursion_limit = l;
234 Initializes the interpreter.
242 * init/init_pmc may be called internally (from thread creation in
243 * ParrotThread::init_pmc() or stand-alone
244 * so we check, if the interpreter is already set up
246 if (!PMC_data(SELF)) {
247 Parrot_ParrotInterpreter_attributes * const attrs =
248 mem_gc_allocate_zeroed_typed(INTERP, Parrot_ParrotInterpreter_attributes);
249 PMC_data(SELF) = attrs;
251 if (!PMC_interp(SELF)) {
252 create_interp(SELF, INTERP);
254 PObj_custom_destroy_SET(SELF);
259 =item C<void init_pmc(PMC *parent)>
261 Initializes a child interpreter with C<*parent> if C<parent> is
262 a ParrotInterpreter instance. Otherwise takes the thread ID from
263 C<parent> and uses that thread.
269 VTABLE void init_pmc(PMC *parent) {
270 /* XXX Can this be moved inside the block where it's used */
271 Parrot_Interp p = PMC_interp(parent);
273 if (!PMC_data(SELF)) {
274 Parrot_ParrotInterpreter_attributes * const attrs =
275 mem_gc_allocate_zeroed_typed(INTERP, Parrot_ParrotInterpreter_attributes);
276 PMC_data(SELF) = attrs;
278 if (!PMC_interp(SELF)) {
279 create_interp(SELF, p);
281 PObj_custom_destroy_SET(SELF);
287 =item C<void destroy()>
295 VTABLE void destroy() {
296 if (PMC_data(SELF)) {
297 mem_gc_free(INTERP, PMC_data(SELF));
298 PMC_data(SELF) = NULL;
305 =item C<void set_pointer(void *value)>
307 Sets C<struct_val> to C<*value>.
313 VTABLE void set_pointer(void *value) {
315 /* XXX: init_world in src/global_setup.c needs to create a
316 * ParrotInterpreter through Parrot_pmc_new_noinit. If this PMC hasn't been
317 * initialized, cheat by initializing instead. */
318 if (!PMC_data(SELF)) {
319 Parrot_ParrotInterpreter_attributes * const attrs =
320 mem_gc_allocate_zeroed_typed(INTERP, Parrot_ParrotInterpreter_attributes);
321 PMC_data(SELF) = attrs;
322 PObj_custom_destroy_SET(SELF);
324 PMC_interp(SELF) = (struct parrot_interp_t *)value;
329 =item C<void *get_pointer()>
331 Returns C<struct_val>.
337 VTABLE void *get_pointer() {
338 return PMC_interp(SELF);
343 =item C<INTVAL get_integer()>
345 Returns the thread id of the interpreter.
351 VTABLE INTVAL get_integer() {
352 const Parrot_Interp i = PMC_interp(SELF);
354 return (INTVAL)i->thread_data->tid;
360 =item C<opcode_t *invoke(void *next)>
362 Runs the interpreter's byte code.
368 VTABLE opcode_t *invoke(void *next) {
369 Interp * const new_interp = PMC_interp(SELF);
372 pt_thread_prepare_for_run(new_interp, INTERP);
374 /* TODO pass arguments from parent (interp) to child (new_interp) by
375 * possibly clone of share the arguments r/o args can be passed as is */
377 /* calculate offset and run */
378 runops(new_interp, (size_t)((opcode_t *)PMC_sub(SELF) -
379 (opcode_t *)INTERP->code->base.data));
381 return (opcode_t *)next;
386 =item C<PMC *get_pmc()>
388 Return this Thread's args.
394 VTABLE PMC *get_pmc() {
395 return PMC_args(SELF);
400 =item C<void set_pmc(PMC *args)>
402 Set this Thread's args.
408 VTABLE void set_pmc(PMC *args) {
409 PMC_args(SELF) = args;
415 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
417 Returns the PMC global value for C<key>.
423 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
424 Interp * const new_interp = PMC_interp(SELF);
426 if (key >= 0 && key < IGLOBALS_SIZE)
427 return VTABLE_get_pmc_keyed_int(new_interp,
428 new_interp->iglobals, key);
430 /* quick hack to get the global stash */
432 return new_interp->root_namespace;
439 =item C<PMC *get_pmc_keyed(PMC *key)>
441 Introspection interface. C<key> can be:
443 "context" ... return Context PMC
444 "sub" ... return Sub object of this subroutine
445 "continuation" ... return Continuation PMC
446 "lexpad" ... return lexpad PMC for this sub
447 "namespace" ... return namespace PMC for this sub
448 "outer" ... return outer sub of this closure
449 "<item>"; level ... same for caller <level>
450 "annotations"; level > 0 ... annotations at point of call <level>s down
451 "outer"; "<item>" ... same for outer level 1
452 "outer"; "<item>"; level ... same for outer <level>
453 "globals" ... return global stash
459 VTABLE PMC *get_pmc_keyed(PMC *key) {
461 STRING *outer = NULL;
462 STRING *item = key_string(INTERP, key);
463 STRING *name = CONST_STRING(INTERP, "globals");
468 if (Parrot_str_equal(INTERP, item, name))
469 return INTERP->root_namespace;
471 name = CONST_STRING(INTERP, "outer");
473 if (Parrot_str_equal(INTERP, item, name)) {
475 nextkey = key_next(INTERP, key);
477 if (nextkey && (PObj_get_FLAGS(nextkey) & KEY_string_FLAG)) {
479 item = VTABLE_get_string(INTERP, key);
483 nextkey = key_next(INTERP, key);
486 level = VTABLE_get_integer(INTERP, nextkey);
491 Parrot_ex_throw_from_c_args(INTERP, NULL, CONTROL_ERROR,
492 "No such caller depth");
494 ctx = CURRENT_CONTEXT(INTERP);
497 for (; level; --level) {
498 ctx = Parrot_pcc_get_outer_ctx(INTERP, ctx);
499 if (PMC_IS_NULL(ctx))
500 Parrot_ex_throw_from_c_args(INTERP, NULL,
501 CONTROL_ERROR, "No such outer depth");
505 for (; level; --level) {
506 PMC * const cont = Parrot_pcc_get_continuation(INTERP, ctx);
508 if (PMC_IS_NULL(cont) || !PARROT_CONTINUATION(cont)->seg)
509 Parrot_ex_throw_from_c_args(INTERP, NULL,
510 CONTROL_ERROR, "No such caller depth");
512 ctx = PARROT_CONTINUATION(cont)->to_ctx;
514 if (PMC_IS_NULL(Parrot_pcc_get_sub(INTERP, ctx)))
515 Parrot_ex_throw_from_c_args(INTERP, NULL,
516 CONTROL_ERROR, "No such caller depth");
521 return Parrot_pcc_get_sub(INTERP, ctx);
523 name = CONST_STRING(INTERP, "context");
525 if (Parrot_str_equal(INTERP, item, name))
528 name = CONST_STRING(INTERP, "sub");
530 if (Parrot_str_equal(INTERP, item, name))
531 return Parrot_pcc_get_sub(INTERP, ctx);
533 name = CONST_STRING(INTERP, "lexpad");
535 if (Parrot_str_equal(INTERP, item, name))
536 return Parrot_pcc_get_lex_pad(INTERP, ctx);
538 name = CONST_STRING(INTERP, "namespace");
540 if (Parrot_str_equal(INTERP, item, name))
541 return Parrot_pcc_get_namespace(INTERP, ctx);
543 name = CONST_STRING(INTERP, "continuation");
545 if (Parrot_str_equal(INTERP, item, name))
546 return VTABLE_clone(INTERP, Parrot_pcc_get_continuation(INTERP, ctx));
548 name = CONST_STRING(INTERP, "annotations");
550 if (Parrot_str_equal(INTERP, item, name)) {
551 PMC *sub_pmc = Parrot_pcc_get_sub(INTERP, ctx);
552 if (ctx == CURRENT_CONTEXT(INTERP)) {
553 /* We can't know the current program counter for the currently
554 * executing sub, so can't return annotations for that. */
555 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
556 "Cannot get annotations at depth 0; use annotations op instead.");
558 if (!PMC_IS_NULL(sub_pmc)
559 && sub_pmc->vtable->base_type == enum_class_Sub) {
560 Parrot_Sub_attributes *sub;
561 PackFile_ByteCode *seg;
562 opcode_t *pc = Parrot_pcc_get_pc(INTERP, ctx);
564 PMC_get_sub(INTERP, sub_pmc, sub);
567 if (sub->seg->annotations)
568 return PackFile_Annotations_lookup(INTERP, seg->annotations,
569 pc - seg->base.data, NULL);
572 return Parrot_pmc_new(INTERP, enum_class_Hash);
575 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
576 "No such item %Ss", item);
581 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
583 Returns the interpreter info for C<key>.
589 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
590 Interp * const new_interp = PMC_interp(SELF);
593 return (INTVAL)new_interp->flags;
595 return interpinfo(new_interp, key);
600 =item C<void set_integer_keyed_int(INTVAL key, INTVAL val)>
602 Sets the interpreter info for C<key> to C<val>.
608 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL val) {
609 Interp * const new_interp = PMC_interp(SELF);
611 /* set interpreter flags */
613 const INTVAL allowed = PARROT_BOUNDS_FLAG | PARROT_PROFILE_FLAG |
614 PARROT_GC_DEBUG_FLAG;
615 Parrot_clear_flag(new_interp, allowed);
616 Parrot_set_flag(new_interp, val & allowed);
622 =item C<PMC *clone()>
624 First attempt to make things running, and to see, where problems may
625 arise. Only minimal items are done yet.
627 XXX this should of course call C<Parrot_clone()> and use freeze/thaw.
633 VTABLE PMC *clone() {
634 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
636 clone_interpreter(PMC_interp(dest),
637 PMC_interp(SELF), PARROT_CLONE_DEFAULT);
644 =item C<INTVAL is_equal(PMC *val)>
646 Returns whether the interpreter is equal to C<*val>.
648 Two interpreters (threads) are equal if both are non-threaded or they
649 have the same thread id.
655 MULTI INTVAL is_equal(ParrotInterpreter val) {
656 Parrot_Interp self = PMC_interp(SELF);
657 Parrot_Interp other = PMC_interp(val);
659 if (!self->thread_data && !other->thread_data)
662 if (self->thread_data && other->thread_data &&
663 self->thread_data->tid == other->thread_data->tid)
669 MULTI INTVAL is_equal(ParrotThread value) {
670 Parrot_Interp self = PMC_interp(SELF);
672 if (!self->thread_data)
675 return self->thread_data->tid == (UINTVAL) VTABLE_get_integer(INTERP, value);
678 MULTI INTVAL is_equal(DEFAULT value) {
679 Parrot_ex_throw_from_c_args(INTERP, NULL,
680 EXCEPTION_INTERNAL_NOT_IMPLEMENTED,
681 "ParrotInterpreter: no multiple dispatch variant 'is_equal' for %Ss",
682 VTABLE_name(INTERP, value));
687 =item C<void visit(PMC *info)>
689 This is used by freeze/thaw to visit the contents of the interpreter.
691 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
693 =item C<void freeze(PMC *info)>
695 Used to archive the interpreter. Actually not the whole interpreter is
696 frozen but the state of the interpreter, which includes everything that
697 has changes since creating an empty interpreter.
699 =item C<void thaw(PMC *info)>
701 Used to unarchive the interpreter. This merges the changes into this
702 interpreter instance.
704 =item C<void thawfinish(PMC *info)>
712 VTABLE void visit(PMC *info) {
714 * the information frozen here is part of all PBCs
715 * we probably need to freeze all dynamic extensible
716 * mappings (or at least the dynamic part)
718 * charsets idx - name
719 * encodings idx - name
720 * pmc types idx - name
721 * dynamic oplibs opcode nr - opname
723 * The machine thawing this info still needs to load
724 * these extensions, but the order of loading could be
727 * creating all these info as standard PMCs would vastly
728 * simplify this process
730 * thaw would then need a merge operation:
731 * - compare existing for sanity
736 if (VTABLE_get_integer(INTERP, info) == VISIT_THAW_NORMAL ||
737 VTABLE_get_integer(INTERP, info) == VISIT_THAW_CONSTANTS) {
738 VISIT_PMC(INTERP, info, PMC_args(SELF));
741 VISIT_PMC(INTERP, info, INTERP->HLL_info);
745 VTABLE void thaw(PMC *info) {
746 if (!PMC_data(SELF)) {
747 Parrot_ParrotInterpreter_attributes * const attrs =
748 mem_gc_allocate_zeroed_typed(INTERP, Parrot_ParrotInterpreter_attributes);
749 PMC_data(SELF) = attrs;
750 PObj_custom_destroy_SET(SELF);
753 PMC_interp(SELF) = INTERP;
756 VTABLE void thawfinish(PMC *info) {
757 PMC * const new_info = PMC_args(SELF);
758 const INTVAL m = VTABLE_elements(INTERP, new_info);
762 PMC_args(SELF) = NULL;
765 /* TODO compare old entries */
767 for (i = 0; i < m; ++i) {
768 PMC * const entry = VTABLE_get_pmc_keyed_int(INTERP, new_info, i);
769 PMC * const lib_pmc = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_lib);
770 PMC * const name_pmc = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_name);
771 PMC * const typemap = VTABLE_get_pmc_keyed_int(INTERP, entry, e_HLL_typemap);
774 if (!PMC_IS_NULL(name_pmc)) {
775 STRING * const hll_name = VTABLE_get_string(INTERP, name_pmc);
777 hll_id = Parrot_register_HLL(INTERP, hll_name);
780 if (!PMC_IS_NULL(lib_pmc)) {
781 STRING * const lib_name = VTABLE_get_string(INTERP, lib_pmc);
783 if (!STRING_IS_EMPTY(lib_name)) {
784 PMC * const ignored = Parrot_load_lib(INTERP, lib_name, NULL);
785 const INTVAL id = Parrot_register_HLL_lib(INTERP, lib_name);
790 if (hll_id >= 0 && !PMC_IS_NULL(typemap)) {
791 PMC * const iter = VTABLE_get_iter(INTERP, typemap);
792 const INTVAL e = VTABLE_get_integer(INTERP, typemap);
795 for (i = 0; i < e; ++i) {
796 PMC * const key = VTABLE_shift_pmc(INTERP, iter);
797 const INTVAL core_type = VTABLE_get_integer(INTERP, key);
798 const INTVAL hll_type =
799 VTABLE_get_integer_keyed_int(INTERP, typemap, core_type);
801 Parrot_register_HLL_type(INTERP, hll_id,
802 core_type, hll_type);
809 Parrot_gc_mark_and_sweep(PMC_interp(SELF), 0);
814 =item METHOD hll_map(PMC core_type,PMC hll_type)
816 Map core_type to hll_type.
822 METHOD hll_map(PMC *core_type, PMC *hll_type) {
823 const INTVAL core_type_id = VTABLE_type(INTERP, core_type);
824 const INTVAL hll_type_id = VTABLE_type(INTERP, hll_type);
825 const INTVAL hll_id = Parrot_pcc_get_HLL(INTERP, CURRENT_CONTEXT(INTERP));
826 Parrot_register_HLL_type(INTERP, hll_id, core_type_id, hll_type_id);
831 =item METHOD stdhandle(INTVAL fileno, PMC *newhandle :optional)
833 Returns the standard parrot handler associated with the interpreter.
834 The valid values for fileno are listed in include/stdio.pasm
836 Optionally sets the parrot handler passed as second argument
837 as the specified standard handler.
839 This method is experimental. See TT #264.
845 METHOD stdhandle(INTVAL fileno, PMC *newhandle :optional) {
846 PMC * const handle = Parrot_io_stdhandle(INTERP, fileno, newhandle);
847 Parrot_warn_deprecated(INTERP, "stdhandle method is experimental");
853 =item METHOD getpid()
855 Returns the pid of the current process, 0 in platforms that doesn't
858 This method is experimental. See TT #1564.
865 INTVAL id = Parrot_getpid();
881 * c-file-style: "parrot"
883 * vim: expandtab shiftwidth=4: