2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/sub.c - Subroutines
11 Subroutines, continuations, co-routines and other fun stuff...
21 #include "parrot/parrot.h"
22 #include "parrot/oplib/ops.h"
25 /* HEADERIZER HFILE: include/parrot/sub.h */
29 =item C<void mark_context>
31 Marks the context C<*ctx>.
38 mark_context(PARROT_INTERP
, ARGMOD(parrot_context_t
* ctx
))
43 obj
= (PObj
*)ctx
->current_sub
;
45 pobject_lives(interp
, obj
);
47 obj
= (PObj
*)ctx
->current_object
;
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
);
65 mark_context(interp
, ctx
->caller_ctx
);
67 obj
= (PObj
*)ctx
->current_namespace
;
69 pobject_lives(interp
, obj
);
71 obj
= (PObj
*)ctx
->lex_pad
;
73 pobject_lives(interp
, obj
);
75 if (!ctx
->n_regs_used
)
78 for (i
= 0; i
< ctx
->n_regs_used
[REGNO_PMC
]; ++i
) {
79 obj
= (PObj
*)CTX_REG_PMC(ctx
, i
);
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
);
87 pobject_lives(interp
, obj
);
93 =item C<Parrot_sub * new_sub>
95 Returns a new C<Parrot_sub>.
102 PARROT_CANNOT_RETURN_NULL
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
;
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.
125 PARROT_CANNOT_RETURN_NULL
127 new_closure(PARROT_INTERP
)
129 Parrot_sub
* const newsub
= new_sub(interp
);
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.
146 PARROT_CANNOT_RETURN_NULL
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
);
154 cc
->from_ctx
= CONTEXT(interp
);
155 cc
->dynamic_state
= NULL
;
157 CONTEXT(interp
)->ref_count
++;
160 cc
->address
= to
->address
;
163 cc
->seg
= interp
->code
;
166 cc
->current_results
= to_ctx
->current_results
;
172 =item C<Parrot_cont * new_ret_continuation>
174 Returns a new C<Parrot_cont> pointing to the current context.
181 PARROT_CANNOT_RETURN_NULL
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
;
191 cc
->seg
= interp
->code
;
192 cc
->current_results
= NULL
;
199 =item C<Parrot_coro * new_coroutine>
201 Returns a new C<Parrot_coro>.
203 XXX: Need to document semantics in detail.
210 PARROT_CANNOT_RETURN_NULL
212 new_coroutine(PARROT_INTERP
)
214 Parrot_coro
* const co
= mem_allocate_zeroed_typed(Parrot_coro
);
216 co
->seg
= interp
->code
;
218 co
->dynamic_state
= NULL
;
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.
236 PARROT_CANNOT_RETURN_NULL
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
);
247 =item C<void invalidate_retc_context>
249 Make true Continuations from all RetContinuations up the call chain.
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
);
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
])
269 cont
->vtable
= interp
->vtables
[enum_class_Continuation
];
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.
288 PARROT_CAN_RETURN_NULL
289 PARROT_WARN_UNUSED_RESULT
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
)) {
301 STRING
*j
= CONST_STRING(interp
, ";");
304 Parrot_block_GC_mark(interp
);
305 ns_array
= Parrot_ns_get_name(interp
, s
->namespace_stash
);
307 VTABLE_push_string(interp
, ns_array
, s
->name
);
309 res
= string_join(interp
, j
, ns_array
);
310 Parrot_unblock_GC_mark(interp
);
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.
331 Parrot_Context_get_info(PARROT_INTERP
, ARGIN(const parrot_context_t
*ctx
),
332 ARGOUT(Parrot_Context_info
*info
))
337 /* set file/line/pc defaults */
338 info
->file
= CONST_STRING(interp
, "(unknown file)");
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);
354 /* fetch Parrot_sub of the current sub in the given context */
355 if (!VTABLE_isa(interp
, ctx
->current_sub
, CONST_STRING(interp
, "Sub")))
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
;
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
)
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
;
383 opcode_t
*pc
= sub
->seg
->base
.data
;
384 PackFile_Debug
* const debug
= sub
->seg
->debugs
;
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
)
395 /* set source line and file */
396 info
->line
= debug
->base
.data
[i
];
397 info
->file
= Parrot_debug_pc_to_filename(interp
, debug
, i
);
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
;
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
420 PARROT_CAN_RETURN_NULL
421 PARROT_WARN_UNUSED_RESULT
423 Parrot_Context_infostr(PARROT_INTERP
, ARGIN(const parrot_context_t
*ctx
))
425 Parrot_Context_info info
;
427 const char * const msg
= (CONTEXT(interp
) == ctx
)
431 Parrot_block_GC_mark(interp
);
432 if (Parrot_Context_get_info(interp
, ctx
, &info
)) {
433 static const char unknown_file
[] = "(unknown file)";
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
);
447 =item C<PMC* Parrot_find_pad>
449 Locate the LexPad containing the given name. Return NULL on failure.
455 PARROT_CAN_RETURN_NULL
456 PARROT_WARN_UNUSED_RESULT
458 Parrot_find_pad(PARROT_INTERP
, ARGIN(STRING
*lex_name
), ARGIN(const parrot_context_t
*ctx
))
461 PMC
* const lex_pad
= ctx
->lex_pad
;
462 const parrot_context_t
* const outer
= ctx
->outer_ctx
;
467 if (!PMC_IS_NULL(lex_pad
))
468 if (VTABLE_exists_keyed_str(interp
, lex_pad
, lex_name
))
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.",
489 =item C<PMC* parrot_new_closure>
493 Creates a new closure, saving the context information. Takes a pointer
496 Returns a pointer to the closure, (or throws exceptions if invalid).
503 PARROT_CANNOT_RETURN_NULL
504 PARROT_WARN_UNUSED_RESULT
506 parrot_new_closure(PARROT_INTERP
, ARGIN(PMC
*sub_pmc
))
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 */
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
);
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
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.
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
);
594 if (Interp_debug_TEST(interp
, PARROT_CTX_DESTROY_DEBUG_FLAG
))
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
);
600 real_exception(interp
, NULL
, INVALID_OPERATION
,
601 "Continuation invoked after deactivation.");
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.
617 Parrot_continuation_rewind_environment(PARROT_INTERP
, ARGIN(PMC
*pmc
),
618 ARGIN(Parrot_cont
*cc
))
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.]
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
;
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
;
652 if (! interp
->dynamic_env
)
653 real_exception(interp
, NULL
, 1, "Control stack damaged");
655 e
= stack_entry(interp
, interp
->dynamic_env
, 0);
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
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. */
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. */
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
);
713 CONTEXT(interp
) = to_ctx
;
714 interp
->ctx
.bp
= to_ctx
->bp
;
715 interp
->ctx
.bp_ps
= to_ctx
->bp_ps
;
724 F<include/parrot/sub.h>.
728 Initial version by Melvin on 2002/06/6.
737 * c-file-style: "parrot"
739 * vim: expandtab shiftwidth=4: