Tagging trunk at r29452 so that the noautopack can later be synched to it.
[parrot.git] / src / sub.c
blob4b203ce10cf44ea098733ab7efa12b9b5fbd85f2
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/sub.c - Subroutines
9 =head1 DESCRIPTION
11 Subroutines, continuations, co-routines and other fun stuff...
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/oplib/ops.h"
23 #include "sub.str"
25 /* HEADERIZER HFILE: include/parrot/sub.h */
29 =item C<void mark_context>
31 Marks the context C<*ctx>.
33 =cut
37 void
38 mark_context(PARROT_INTERP, ARGMOD(parrot_context_t* ctx))
40 PObj *obj;
41 int i;
43 obj = (PObj *)ctx->current_sub;
44 if (obj)
45 pobject_lives(interp, obj);
47 obj = (PObj *)ctx->current_object;
48 if (obj)
49 pobject_lives(interp, obj);
51 /* the current continuation in the interpreter has
52 * to be marked too in the call sequence currently
53 * as e.g. a MMD search could need resources
54 * and GC the continuation
56 obj = (PObj *)interp->current_cont;
57 if (obj && obj != (PObj *)NEED_CONTINUATION)
58 pobject_lives(interp, obj);
60 obj = (PObj *)ctx->current_cont;
61 if (obj && !PObj_live_TEST(obj))
62 pobject_lives(interp, obj);
64 if (ctx->caller_ctx)
65 mark_context(interp, ctx->caller_ctx);
67 obj = (PObj *)ctx->current_namespace;
68 if (obj)
69 pobject_lives(interp, obj);
71 obj = (PObj *)ctx->lex_pad;
72 if (obj)
73 pobject_lives(interp, obj);
75 if (!ctx->n_regs_used)
76 return;
78 for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; ++i) {
79 obj = (PObj *)CTX_REG_PMC(ctx, i);
80 if (obj)
81 pobject_lives(interp, obj);
84 for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
85 obj = (PObj *)CTX_REG_STR(ctx, i);
86 if (obj)
87 pobject_lives(interp, obj);
93 =item C<Parrot_sub * new_sub>
95 Returns a new C<Parrot_sub>.
97 =cut
101 PARROT_MALLOC
102 PARROT_CANNOT_RETURN_NULL
103 Parrot_sub *
104 new_sub(PARROT_INTERP)
106 /* Using system memory until I figure out GC issues */
107 Parrot_sub * const newsub = mem_allocate_zeroed_typed(Parrot_sub);
108 newsub->seg = interp->code;
109 return newsub;
114 =item C<Parrot_sub * new_closure>
116 Returns a new C<Parrot_sub> with its own sctatchpad.
118 XXX: Need to document semantics in detail.
120 =cut
124 PARROT_MALLOC
125 PARROT_CANNOT_RETURN_NULL
126 Parrot_sub *
127 new_closure(PARROT_INTERP)
129 Parrot_sub * const newsub = new_sub(interp);
130 return newsub;
135 =item C<Parrot_cont * new_continuation>
137 Returns a new C<Parrot_cont> to the context of C<to> with its own copy of the
138 current interpreter context. If C<to> is C<NULL>, then the C<to_ctx> is set
139 to the current context.
141 =cut
145 PARROT_MALLOC
146 PARROT_CANNOT_RETURN_NULL
147 Parrot_cont *
148 new_continuation(PARROT_INTERP, ARGIN_NULLOK(const Parrot_cont *to))
150 Parrot_cont * const cc = mem_allocate_typed(Parrot_cont);
151 Parrot_Context * const to_ctx = to ? to->to_ctx : CONTEXT(interp);
153 cc->to_ctx = to_ctx;
154 cc->from_ctx = CONTEXT(interp);
155 cc->dynamic_state = NULL;
156 cc->runloop_id = 0;
157 CONTEXT(interp)->ref_count++;
158 if (to) {
159 cc->seg = to->seg;
160 cc->address = to->address;
162 else {
163 cc->seg = interp->code;
164 cc->address = NULL;
166 cc->current_results = to_ctx->current_results;
167 return cc;
172 =item C<Parrot_cont * new_ret_continuation>
174 Returns a new C<Parrot_cont> pointing to the current context.
176 =cut
180 PARROT_MALLOC
181 PARROT_CANNOT_RETURN_NULL
182 Parrot_cont *
183 new_ret_continuation(PARROT_INTERP)
185 Parrot_cont * const cc = mem_allocate_typed(Parrot_cont);
187 cc->to_ctx = CONTEXT(interp);
188 cc->from_ctx = NULL; /* filled in during a call */
189 cc->dynamic_state = NULL;
190 cc->runloop_id = 0;
191 cc->seg = interp->code;
192 cc->current_results = NULL;
193 cc->address = NULL;
194 return cc;
199 =item C<Parrot_coro * new_coroutine>
201 Returns a new C<Parrot_coro>.
203 XXX: Need to document semantics in detail.
205 =cut
209 PARROT_MALLOC
210 PARROT_CANNOT_RETURN_NULL
211 Parrot_coro *
212 new_coroutine(PARROT_INTERP)
214 Parrot_coro * const co = mem_allocate_zeroed_typed(Parrot_coro);
216 co->seg = interp->code;
217 co->ctx = NULL;
218 co->dynamic_state = NULL;
220 return co;
225 =item C<PMC * new_ret_continuation_pmc>
227 Returns a new C<RetContinuation> PMC. Uses one from the cache,
228 if possible; otherwise, creates a new one.
230 =cut
234 PARROT_API
235 PARROT_MALLOC
236 PARROT_CANNOT_RETURN_NULL
237 PMC *
238 new_ret_continuation_pmc(PARROT_INTERP, ARGIN_NULLOK(opcode_t *address))
240 PMC* const continuation = pmc_new(interp, enum_class_RetContinuation);
241 VTABLE_set_pointer(interp, continuation, address);
242 return continuation;
247 =item C<void invalidate_retc_context>
249 Make true Continuations from all RetContinuations up the call chain.
251 =cut
255 void
256 invalidate_retc_context(PARROT_INTERP, ARGMOD(PMC *cont))
258 Parrot_Context *ctx = PMC_cont(cont)->from_ctx;
260 Parrot_set_context_threshold(interp, ctx);
261 while (1) {
263 * We stop if we encounter a true continuation, because
264 * if one were created, everything up the chain would have been
265 * invalidated earlier.
267 if (cont->vtable != interp->vtables[enum_class_RetContinuation])
268 break;
269 cont->vtable = interp->vtables[enum_class_Continuation];
270 ctx->ref_count++;
271 cont = ctx->current_cont;
272 ctx = PMC_cont(cont)->from_ctx;
279 =item C<STRING* Parrot_full_sub_name>
281 Return namespace, name, and location of subroutine.
283 =cut
287 PARROT_API
288 PARROT_CAN_RETURN_NULL
289 PARROT_WARN_UNUSED_RESULT
290 STRING*
291 Parrot_full_sub_name(PARROT_INTERP, ARGIN_NULLOK(PMC* sub))
293 if (sub && VTABLE_defined(interp, sub)) {
294 Parrot_sub * const s = PMC_sub(sub);
296 if (PMC_IS_NULL(s->namespace_stash)) {
297 return s->name;
299 else {
300 PMC *ns_array;
301 STRING *j = CONST_STRING(interp, ";");
302 STRING *res;
304 Parrot_block_GC_mark(interp);
305 ns_array = Parrot_ns_get_name(interp, s->namespace_stash);
306 if (s->name)
307 VTABLE_push_string(interp, ns_array, s->name);
309 res = string_join(interp, j, ns_array);
310 Parrot_unblock_GC_mark(interp);
311 return res;
314 return NULL;
319 =item C<int Parrot_Context_get_info>
321 Takes pointers to a context and its information table.
322 Populates the table and returns 0 or 1. XXX needs explanation
323 Used by Parrot_Context_infostr.
325 =cut
329 PARROT_API
331 Parrot_Context_get_info(PARROT_INTERP, ARGIN(const parrot_context_t *ctx),
332 ARGOUT(Parrot_Context_info *info))
334 Parrot_sub *sub;
335 DECL_CONST_CAST;
337 /* set file/line/pc defaults */
338 info->file = CONST_STRING(interp, "(unknown file)");
339 info->line = -1;
340 info->pc = -1;
341 info->nsname = NULL;
342 info->subname = NULL;
343 info->fullname = NULL;
345 /* is the current sub of the specified context valid? */
346 if (PMC_IS_NULL(ctx->current_sub)) {
347 info->subname = string_from_cstring(interp, "???", 3);
348 info->nsname = info->subname;
349 info->fullname = string_from_cstring(interp, "??? :: ???", 10);
350 info->pc = -1;
351 return 0;
354 /* fetch Parrot_sub of the current sub in the given context */
355 if (!VTABLE_isa(interp, ctx->current_sub, CONST_STRING(interp, "Sub")))
356 return 1;
358 sub = PMC_sub(ctx->current_sub);
359 /* set the sub name */
360 info->subname = sub->name;
362 /* set the namespace name and fullname of the sub */
363 if (PMC_IS_NULL(sub->namespace_name)) {
364 info->nsname = string_from_literal(interp, "");
365 info->fullname = info->subname;
367 else {
368 info->nsname = VTABLE_get_string(interp, sub->namespace_name);
369 info->fullname = Parrot_full_sub_name(interp, ctx->current_sub);
372 /* return here if there is no current pc */
373 if (ctx->current_pc == NULL)
374 return 1;
376 /* calculate the current pc */
377 info->pc = ctx->current_pc - sub->seg->base.data;
379 /* determine the current source file/line */
380 if (ctx->current_pc) {
381 const size_t offs = info->pc;
382 size_t i, n;
383 opcode_t *pc = sub->seg->base.data;
384 PackFile_Debug * const debug = sub->seg->debugs;
386 if (!debug)
387 return 0;
388 for (i = n = 0; n < sub->seg->base.size; i++) {
389 op_info_t * const op_info = &interp->op_info_table[*pc];
390 opcode_t var_args = 0;
392 if (i >= debug->base.size)
393 return 0;
394 if (n >= offs) {
395 /* set source line and file */
396 info->line = debug->base.data[i];
397 info->file = Parrot_debug_pc_to_filename(interp, debug, i);
398 break;
400 ADD_OP_VAR_PART(interp, sub->seg, pc, var_args);
401 n += op_info->op_count + var_args;
402 pc += op_info->op_count + var_args;
405 return 1;
410 =item C<STRING* Parrot_Context_infostr>
412 Formats context information for display. Takes a context pointer and
413 returns a pointer to the text. Used in debug.c and warnings.c
415 =cut
419 PARROT_API
420 PARROT_CAN_RETURN_NULL
421 PARROT_WARN_UNUSED_RESULT
422 STRING*
423 Parrot_Context_infostr(PARROT_INTERP, ARGIN(const parrot_context_t *ctx))
425 Parrot_Context_info info;
426 STRING *res = NULL;
427 const char * const msg = (CONTEXT(interp) == ctx)
428 ? "current instr.:"
429 : "called from Sub";
431 Parrot_block_GC_mark(interp);
432 if (Parrot_Context_get_info(interp, ctx, &info)) {
433 static const char unknown_file[] = "(unknown file)";
434 DECL_CONST_CAST;
436 res = Parrot_sprintf_c(interp,
437 "%s '%Ss' pc %d (%Ss:%d)", msg,
438 info.fullname, info.pc, info.file, info.line);
441 Parrot_unblock_GC_mark(interp);
442 return res;
447 =item C<PMC* Parrot_find_pad>
449 Locate the LexPad containing the given name. Return NULL on failure.
451 =cut
455 PARROT_CAN_RETURN_NULL
456 PARROT_WARN_UNUSED_RESULT
457 PMC*
458 Parrot_find_pad(PARROT_INTERP, ARGIN(STRING *lex_name), ARGIN(const parrot_context_t *ctx))
460 while (1) {
461 PMC * const lex_pad = ctx->lex_pad;
462 const parrot_context_t * const outer = ctx->outer_ctx;
464 if (!outer)
465 return lex_pad;
467 if (!PMC_IS_NULL(lex_pad))
468 if (VTABLE_exists_keyed_str(interp, lex_pad, lex_name))
469 return lex_pad;
471 #if CTX_LEAK_DEBUG
472 if (outer == ctx) {
473 /* This is a bug; a context can never be its own :outer context.
474 * Detecting it avoids an unbounded loop, which is difficult to
475 * debug, though we'd rather not pay the cost of detection in a
476 * production release.
478 real_exception(interp, NULL, INVALID_OPERATION,
479 "Bug: Context %p :outer points back to itself.",
480 ctx);
482 #endif
483 ctx = outer;
489 =item C<PMC* parrot_new_closure>
491 Used where? XXX
493 Creates a new closure, saving the context information. Takes a pointer
494 to a subroutine.
496 Returns a pointer to the closure, (or throws exceptions if invalid).
498 =cut
502 PARROT_API
503 PARROT_CANNOT_RETURN_NULL
504 PARROT_WARN_UNUSED_RESULT
505 PMC*
506 parrot_new_closure(PARROT_INTERP, ARGIN(PMC *sub_pmc))
508 PMC *cont;
510 PMC * const clos_pmc = VTABLE_clone(interp, sub_pmc);
511 Parrot_sub * const sub = PMC_sub(sub_pmc);
512 Parrot_sub * const clos = PMC_sub(clos_pmc);
514 /* the given sub_pmc has to have an :outer(sub) that is this subroutine */
515 Parrot_Context * const ctx = CONTEXT(interp);
517 if (PMC_IS_NULL(sub->outer_sub))
518 real_exception(interp, NULL, INVALID_OPERATION,
519 "'%Ss' isn't a closure (no :outer)", sub->name);
521 /* if (sub->outer_sub != ctx->current_sub) - fails if outer
522 * is a closure too e.g. test 'closure 4' */
523 if (0 == string_equal(interp, (PMC_sub(ctx->current_sub))->name, sub->name))
524 real_exception(interp, NULL, INVALID_OPERATION,
525 "'%Ss' isn't the :outer of '%Ss')",
526 (PMC_sub(ctx->current_sub))->name, sub->name);
528 cont = ctx->current_cont;
530 /* preserve this frame by converting the continuation */
531 cont->vtable = interp->vtables[enum_class_Continuation];
533 /* remember this (the :outer) ctx in the closure */
534 clos->outer_ctx = ctx;
536 /* the closure refs now this context too */
537 ctx->ref_count++;
539 #if CTX_LEAK_DEBUG
540 if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG))
541 fprintf(stderr, "[alloc closure %p, outer_ctx %p, ref_count=%d]\n",
542 (void *)clos_pmc, (void *)ctx, (int) ctx->ref_count);
543 #endif
545 return clos_pmc;
551 =item C<void Parrot_continuation_runloop_check>
553 Verifies that the Parrot_cont contained in the current PMC is not trying to
554 jump runloops. Don't call this for a RetContinuation; that's what it's
555 supposed to do.
559 void
560 Parrot_continuation_runloop_check(PARROT_INTERP, ARGIN(PMC *pmc),
561 ARGIN(Parrot_cont *cc))
564 /* it's ok to exit to "runloop 0"; there is no such
565 runloop, but the only continuation that thinks it came from runloop 0 is
566 for the return from the initial sub call. */
568 if (interp->current_runloop_id != cc->runloop_id
569 && cc->runloop_id != 0)
570 fprintf(stderr, "[oops; continuation %p of type %d "
571 "is trying to jump from runloop %d to runloop %d]\n",
572 (void *)pmc, (int)pmc->vtable->base_type,
573 interp->current_runloop_id, cc->runloop_id);
579 =item C<void Parrot_continuation_check>
581 Verifies that the provided continuation is sane.
585 void
586 Parrot_continuation_check(PARROT_INTERP, ARGIN(PMC *pmc),
587 ARGIN(Parrot_cont *cc))
589 Stack_Chunk_t *stack_target = cc->dynamic_state;
590 parrot_context_t *to_ctx = cc->to_ctx;
591 parrot_context_t *from_ctx = CONTEXT(interp);
593 #if CTX_LEAK_DEBUG
594 if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG))
595 fprintf(stderr,
596 "[invoke cont %p, to_ctx %p, from_ctx %p (refs %d)]\n",
597 (void *)pmc, (void *)to_ctx, (void *)from_ctx, (int)from_ctx->ref_count);
598 #endif
599 if (!to_ctx)
600 real_exception(interp, NULL, INVALID_OPERATION,
601 "Continuation invoked after deactivation.");
602 if (!stack_target)
603 real_exception(interp, NULL, INVALID_OPERATION,
604 "Continuation invoked without initialization.");
610 =item C<void Parrot_continuation_rewind_environment>
612 Restores the appropriate context for the continuation.
616 void
617 Parrot_continuation_rewind_environment(PARROT_INTERP, ARGIN(PMC *pmc),
618 ARGIN(Parrot_cont *cc))
620 int stack_delta = 0;
621 int exception_continuation_p = -1;
622 parrot_context_t *to_ctx = cc->to_ctx;
623 Stack_Chunk_t *stack_target = cc->dynamic_state;
624 Stack_Chunk_t *corresponding_target;
626 /* Rewind the dynamic environment. */
627 if (interp->dynamic_env != stack_target) {
628 /* compute the "stack delta", which is a measure of how much
629 unwinding we have to do. if negative, we have to pop that many
630 entries; if positive, we are going back up the stack.
631 [bug: this is not true rewinding. -- rgr, 30-Sep-06.]
633 stack_delta
634 = ((int) stack_height(interp, stack_target) -
635 (int) stack_height(interp, interp->dynamic_env));
638 /* descend down the target stack until we get to the same depth. */
639 corresponding_target = stack_target;
641 while (stack_delta > 0) {
642 corresponding_target = corresponding_target->prev;
643 stack_delta--;
646 /* both stacks are now at the same depth. pop from both until we reach
647 their common ancestor. */
648 while (interp->dynamic_env != corresponding_target) {
649 PMC *cleanup_sub = NULL;
650 Stack_Entry_t *e;
652 if (! interp->dynamic_env)
653 real_exception(interp, NULL, 1, "Control stack damaged");
655 e = stack_entry(interp, interp->dynamic_env, 0);
657 if (!e)
658 real_exception(interp, NULL, 1, "Control stack damaged");
660 if (e->entry_type == STACK_ENTRY_ACTION) {
662 * Disable automatic cleanup routine execution in stack_pop so
663 * that we can run the action subroutine manually. This is
664 * because we have to run the sub AFTER it has been popped, lest
665 * a new error in the sub cause an infinite loop when invoking
666 * an error handler.
668 cleanup_sub = UVal_pmc(e->entry);
669 e->cleanup = STACK_CLEANUP_NULL;
672 (void)stack_pop(interp, &interp->dynamic_env,
673 NULL, NO_STACK_ENTRY_TYPE);
675 /* Now it's safe to run. */
676 if (cleanup_sub) {
677 if (exception_continuation_p == -1)
678 exception_continuation_p =
679 VTABLE_isa(interp, pmc, CONST_STRING(interp, "Exception_Handler"));
680 Parrot_runops_fromc_args(interp, cleanup_sub,
681 "vI", exception_continuation_p);
684 /* Keep corresponding_target in sync. If stack_delta is negative,
685 * then dynamic_env is still above it; otherwise, we must step
686 * corresponding_target backwards as well. */
687 if (stack_delta < 0)
688 stack_delta++;
689 else {
690 Stack_Chunk_t *prev = corresponding_target->prev;
691 (void)stack_pop(interp, &corresponding_target, NULL,
692 NO_STACK_ENTRY_TYPE);
693 corresponding_target = prev;
697 /* run back up the target stack to our destination. [when we support
698 dynamic binding (e.g.), we will have to traverse back up, and will
699 therefore need to keep track on the way down. -- rgr, 30-Sep-06.] */
700 interp->dynamic_env->refcount--;
701 interp->dynamic_env = stack_target;
703 /* debug print before context is switched */
704 if (Interp_trace_TEST(interp, PARROT_TRACE_SUB_CALL_FLAG)) {
705 PMC *sub = to_ctx->current_sub;
707 PIO_eprintf(interp, "# Back in sub '%Ss', env %p\n",
708 Parrot_full_sub_name(interp, sub),
709 interp->dynamic_env);
712 /* set context */
713 CONTEXT(interp) = to_ctx;
714 interp->ctx.bp = to_ctx->bp;
715 interp->ctx.bp_ps = to_ctx->bp_ps;
720 =back
722 =head1 SEE ALSO
724 F<include/parrot/sub.h>.
726 =head1 HISTORY
728 Initial version by Melvin on 2002/06/6.
730 =cut
736 * Local variables:
737 * c-file-style: "parrot"
738 * End:
739 * vim: expandtab shiftwidth=4: