/* run.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, * 2000, 2001, 2004, 2005, 2006, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * */ /* This file contains the main Perl opcode execution loop. It just * calls the pp_foo() function associated with each op, and expects that * function to return a pointer to the next op to be executed, or null if * it's the end of the sub or program or whatever. * * There is a similar loop in dump.c, Perl_runops_debug(), which does * the same, but also checks for various debug flags each time round the * loop. * * Why this function requires a file all of its own is anybody's guess. * DAPM. */ #include "EXTERN.h" #define PERL_IN_RUN_C #include "perl.h" /* * 'Away now, Shadowfax! Run, greatheart, run as you have never run before! * Now we are come to the lands where you were foaled, and every stone you * know. Run now! Hope is in speed!' --Gandalf * * [p.600 of _The Lord of the Rings_, III/xi: "The Palantír"] */ int Perl_runops_standard(pTHX) { OP *op = PL_op; PERL_DTRACE_PROBE_OP(op); while ((PL_op = op = op->op_ppaddr(aTHX))) { PERL_DTRACE_PROBE_OP(op); } PERL_ASYNC_CHECK(); TAINT_NOT; return 0; } #ifdef PERL_RC_STACK /* this is a wrapper for all runops-style functions. It temporarily * reifies the stack if necessary, then calls the real runops function */ int Perl_runops_wrap(pTHX) { /* runops loops assume a ref-counted stack. If we have been called via a * wrapper (pp_wrap or xs_wrap) with the top half of the stack not * reference-counted, or with a non-real stack, temporarily convert it * to reference-counted. This is because the si_stack_nonrc_base * mechanism only allows a single split in the stack, not multiple * stripes. * At the end, we revert the stack (or part thereof) to non-refcounted * to keep whoever our caller is happy. * * If what we call croaks, catch it, revert, then rethrow. */ I32 cut; /* the cut point between refcnted and non-refcnted */ bool was_real = cBOOL(AvREAL(PL_curstack)); I32 old_base = PL_curstackinfo->si_stack_nonrc_base; if (was_real && !old_base) { PL_runops(aTHX); /* call the real loop */ return 0; } if (was_real) { cut = old_base; assert(PL_stack_base + cut <= PL_stack_sp + 1); PL_curstackinfo->si_stack_nonrc_base = 0; } else { assert(!old_base); assert(!AvREIFY(PL_curstack)); AvREAL_on(PL_curstack); /* skip the PL_sv_undef guard at PL_stack_base[0] but still * signal adjusting may be needed on return by setting to a * non-zero value - even if stack is empty */ cut = 1; } if (cut) { SV **svp = PL_stack_base + cut; while (svp <= PL_stack_sp) { SvREFCNT_inc_simple_void(*svp); svp++; } } AV * old_curstack = PL_curstack; /* run the real loop while catching exceptions */ dJMPENV; int ret; JMPENV_PUSH(ret); switch (ret) { case 0: /* normal return from JMPENV_PUSH */ cur_env.je_mustcatch = cur_env.je_prev->je_mustcatch; PL_runops(aTHX); /* call the real loop */ revert: /* revert stack back its non-ref-counted state */ assert(AvREAL(PL_curstack)); if (cut) { /* undo the stack reification that took place at the beginning of * this function */ if (UNLIKELY(!was_real)) AvREAL_off(PL_curstack); SSize_t n = PL_stack_sp - (PL_stack_base + cut) + 1; if (n > 0) { /* we need to decrement the refcount of every SV from cut * upwards; but this may prematurely free them, so * mortalise them instead */ EXTEND_MORTAL(n); for (SSize_t i = 0; i < n; i ++) { SV* sv = PL_stack_base[cut + i]; if (sv) PL_tmps_stack[++PL_tmps_ix] = sv; } } I32 sp1 = PL_stack_sp - PL_stack_base + 1; PL_curstackinfo->si_stack_nonrc_base = old_base > sp1 ? sp1 : old_base; } break; case 3: /* exception trapped by eval - stack only partially unwound */ /* if the exception has already unwound to before the current * stack, no need to fix it up */ if (old_curstack == PL_curstack) goto revert; break; default: break; } JMPENV_POP; if (ret) { JMPENV_JUMP(ret); /* re-throw the exception */ NOT_REACHED; /* NOTREACHED */ } return 0; } #endif /* * ex: set ts=8 sts=4 sw=4 et: */