X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlintern.pod;h=50f3d51af949f34b3e9115ef951b818086c9d2f7;hb=8a2485f87de4ac33d6c8564ae6b27c5efc3e1430;hp=a9915d2fc7cba4feb8e6c882379a82bf37a00b2f;hpb=ad63d80fcd28c3b5fdbb5328f0f8ea29cbce94d8;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlintern.pod b/pod/perlintern.pod index a9915d2..50f3d51 100644 --- a/pod/perlintern.pod +++ b/pod/perlintern.pod @@ -11,6 +11,67 @@ format but are not marked as part of the Perl API. In other words, B! +=head1 CV reference counts and CvOUTSIDE + +=over 8 + +=item CvWEAKOUTSIDE + +Each CV has a pointer, C, to its lexically enclosing +CV (if any). Because pointers to anonymous sub prototypes are +stored in C<&> pad slots, it is a possible to get a circular reference, +with the parent pointing to the child and vice-versa. To avoid the +ensuing memory leak, we do not increment the reference count of the CV +pointed to by C in the I that the parent +has a C<&> pad slot pointing back to us. In this case, we set the +C flag in the child. This allows us to determine under what +circumstances we should decrement the refcount of the parent when freeing +the child. + +There is a further complication with non-closure anonymous subs (ie those +that do not refer to any lexicals outside that sub). In this case, the +anonymous prototype is shared rather than being cloned. This has the +consequence that the parent may be freed while there are still active +children, eg + + BEGIN { $a = sub { eval '$x' } } + +In this case, the BEGIN is freed immediately after execution since there +are no active references to it: the anon sub prototype has +C set since it's not a closure, and $a points to the same +CV, so it doesn't contribute to BEGIN's refcount either. When $a is +executed, the C causes the chain of Cs to be followed, +and the freed BEGIN is accessed. + +To avoid this, whenever a CV and its associated pad is freed, any +C<&> entries in the pad are explicitly removed from the pad, and if the +refcount of the pointed-to anon sub is still positive, then that +child's C is set to point to its grandparent. This will only +occur in the single specific case of a non-closure anon prototype +having one or more active references (such as C<$a> above). + +One other thing to consider is that a CV may be merely undefined +rather than freed, eg C. In this case, its refcount may +not have reached zero, but we still delete its pad and its C etc. +Since various children may still have their C pointing at this +undefined CV, we keep its own C for the time being, so that +the chain of lexical scopes is unbroken. For example, the following +should print 123: + + my $x = 123; + sub tmp { sub { eval '$x' } } + my $a = tmp(); + undef &tmp; + print $a->(); + + bool CvWEAKOUTSIDE(CV *cv) + +=for hackers +Found in file cv.h + + +=back + =head1 Functions in file pad.h @@ -30,7 +91,7 @@ Found in file pad.h Access the SV at offset po in the saved current pad in the given context block structure (can be used as an lvalue). - PAD * CX_CURPAD_SV(struct context, PADOFFSET po) + SV * CX_CURPAD_SV(struct context, PADOFFSET po) =for hackers Found in file pad.h @@ -113,6 +174,25 @@ Clone a padlist. =for hackers Found in file pad.h +=item PAD_RESTORE_LOCAL + +Restore the old pad saved into the local variable opad by PAD_SAVE_LOCAL() + + void PAD_RESTORE_LOCAL(PAD *opad) + +=for hackers +Found in file pad.h + +=item PAD_SAVE_LOCAL + +Save the current pad to the local variable opad, then make the +current pad equal to npad + + void PAD_SAVE_LOCAL(PAD *opad, PAD *npad) + +=for hackers +Found in file pad.h + =item PAD_SAVE_SETNULLPAD Save the current pad then set it to null. @@ -141,6 +221,15 @@ the previous current pad. =for hackers Found in file pad.h +=item PAD_SET_CUR_NOSAVE + +like PAD_SET_CUR, but without the save + + void PAD_SET_CUR_NOSAVE (PADLIST padlist, I32 n) + +=for hackers +Found in file pad.h + =item PAD_SV Get the value at offset C in the current pad @@ -162,15 +251,6 @@ For internal use only. =for hackers Found in file pad.h -=item PAD_UPDATE_CURPAD - -Set PL_curpad from the value of PL_comppad. - - void PAD_UPDATE_CURPAD() - -=for hackers -Found in file pad.h - =item SAVECLEARSV Clear the pointed to pad value on scope exit. (ie the runtime action of 'my') @@ -184,19 +264,11 @@ Found in file pad.h save PL_comppad and PL_curpad - void SAVECOMPPAD() - -=for hackers -Found in file pad.h - -=item SAVEFREEOP - -Free the op on scope exit. At the same time, reset PL_curpad - void SAVEFREEOP (OP *o) + void SAVECOMPPAD() =for hackers Found in file pad.h @@ -205,6 +277,7 @@ Found in file pad.h Save a pad slot (used to restore after an iteration) +XXX DAPM it would make more sense to make the arg a PADOFFSET void SAVEPADSV (PADOFFSET po) =for hackers @@ -213,6 +286,27 @@ Found in file pad.h =back +=head1 Functions in file pp_ctl.c + + +=over 8 + +=item find_runcv + +Locate the CV corresponding to the currently executing sub or eval. +If db_seqp is non_null, skip CVs that are in the DB package and populate +*db_seqp with the cop sequence number at the point that the DB:: code was +entered. (allows debuggers to eval in the scope of the breakpoint rather +than in in the scope of the debugger itself). + + CV* find_runcv(U32 *db_seqp) + +=for hackers +Found in file pp_ctl.c + + +=back + =head1 Global Variables =over 8 @@ -343,14 +437,15 @@ CV's can have CvPADLIST(cv) set to point to an AV. For these purposes "forms" are a kind-of CV, eval""s are too (except they're not callable at will and are always thrown away after the eval"" is done -executing). +executing). Require'd files are simply evals without any outer lexical +scope. XSUBs don't have CvPADLIST set - dXSTARG fetches values from PL_curpad, but that is really the callers pad (a slot of which is allocated by every entersub). The CvPADLIST AV has does not have AvREAL set, so REFCNT of component items -is managed "manual" (mostly in op.c) rather than normal av.c rules. +is managed "manual" (mostly in pad.c) rather than normal av.c rules. The items in the AV are not SVs as for a normal AV, but other AVs: 0'th Entry of the CvPADLIST is an AV which represents the "names" or rather @@ -362,11 +457,14 @@ The 0'th slot of a frame AV is an AV which is @_. other entries are storage for variables and op targets. During compilation: -C is set the the the names AV. -C is set the the frame AV for the frame CvDEPTH == 1. -C is set the body of the frame AV (i.e. AvARRAY(PL_comppad)). +C is set to the names AV. +C is set to the frame AV for the frame CvDEPTH == 1. +C is set to the body of the frame AV (i.e. AvARRAY(PL_comppad)). + +During execution, C and C refer to the live +frame of the currently executing sub. -Itterating over the names AV itterates over all possible pad +Iterating over the names AV iterates over all possible pad items. Pad slots that are SVs_PADTMP (targets/GVs/constants) end up having &PL_sv_undef "names" (see pad_alloc()). @@ -386,14 +484,29 @@ stash of the associated global (so that duplicate C delarations in the same package can be detected). SvCUR is sometimes hijacked to store the generation number during compilation. -If SvFAKE is set on the name SV then slot in the frame AVs are -a REFCNT'ed references to a lexical from "outside". +If SvFAKE is set on the name SV, then that slot in the frame AV is +a REFCNT'ed reference to a lexical from "outside". In this case, +the name SV does not use NVX and IVX to store a cop_seq range, since it is +in scope throughout. Instead IVX stores some flags containing info about +the real lexical (is it declared in an anon, and is it capable of being +instantiated multiple times?), and for fake ANONs, NVX contains the index +within the parent's pad where the lexical's value is stored, to make +cloning quicker. -If the 'name' is '&' the the corresponding entry in frame AV +If the 'name' is '&' the corresponding entry in frame AV is a CV representing a possible closure. (SvFAKE and name of '&' is not a meaningful combination currently but could become so if C is implemented.) +Note that formats are treated as anon subs, and are cloned each time +write is called (if necessary). + +The flag SVf_PADSTALE is cleared on lexicals each time the my() is executed, +and set on scope exit. This allows the 'Variable $x is not available' warning +to be generated in evals, such as + + { my $x = 1; sub f { eval '$x'} } f(); + AV * CvPADLIST(CV *cv) =for hackers @@ -448,14 +561,13 @@ Found in file pad.c =item pad_add_name -Create a new name in the current pad at the specified offset. +Create a new name and associated PADMY SV in the current pad; return the +offset. If C is valid, the name is for a typed lexical; set the name's stash to that value. If C is valid, it's an our lexical, set the name's GvSTASH to that value -Also, if the name is @.. or %.., create a new array or hash for that slot - If fake, it means we're cloning an existing entry PADOFFSET pad_add_name(char *name, HV* typestash, HV* ourstash, bool clone) @@ -499,11 +611,23 @@ Found in file pad.c =item pad_findlex Find a named lexical anywhere in a chain of nested pads. Add fake entries -in the inner pads if its found in an outer one. +in the inner pads if it's found in an outer one. -If flags == FINDLEX_NOSEARCH we don't bother searching outer contexts. +Returns the offset in the bottom pad of the lex or the fake lex. +cv is the CV in which to start the search, and seq is the current cop_seq +to match against. If warn is true, print appropriate warnings. The out_* +vars return values, and so are pointers to where the returned values +should be stored. out_capture, if non-null, requests that the innermost +instance of the lexical is captured; out_name_sv is set to the innermost +matched namesv or fake namesv; out_flags returns the flags normally +associated with the IVX field of a fake namesv. - PADOFFSET pad_findlex(char* name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix, I32 saweval, U32 flags) +Note that pad_findlex() is recursive; it recurses up the chain of CVs, +then comes back down, adding fake entries as it goes. It has to be this way +because fake namesvs in anon protoypes have to store in NVX the index into +the parent pad. + + PADOFFSET pad_findlex(char *name, CV* cv, U32 seq, int warn, SV** out_capture, SV** out_name_sv, int *out_flags) =for hackers Found in file pad.c @@ -524,7 +648,8 @@ Found in file pad.c =item pad_fixup_inner_anons For any anon CVs in the pad, change CvOUTSIDE of that CV from -old_cv to new_cv if necessary. +old_cv to new_cv if necessary. Needed when a newly-compiled CV has to be +moved to a pre-existing CV struct. void pad_fixup_inner_anons(PADLIST *padlist, CV *old_cv, CV *new_cv) @@ -560,7 +685,7 @@ can be OR'ed together: padnew_SAVE save old globals padnew_SAVESUB also save extra stuff for start of sub - PADLIST* pad_new(padnew_flags flags) + PADLIST* pad_new(int flags) =for hackers Found in file pad.c @@ -623,9 +748,12 @@ Free the padlist associated with a CV. If parts of it happen to be current, we null the relevant PL_*pad* global vars so that we don't have any dangling references left. We also repoint the CvOUTSIDE of any about-to-be-orphaned -inner subs to outercv. +inner subs to the outer of this cv. + +(This function should really be called pad_free, but the name was already +taken) - void pad_undef(CV* cv, CV* outercv) + void pad_undef(CV* cv) =for hackers Found in file pad.c @@ -663,11 +791,32 @@ Found in file pp.h =over 8 +=item find_uninit_var + +Find the name of the undefined variable (if any) that caused the operator o +to issue a "Use of uninitialized value" warning. +If match is true, only return a name if it's value matches uninit_sv. +So roughly speaking, if a unary operator (such as OP_COS) generates a +warning, then following the direct child of the op may yield an +OP_PADSV or OP_GV that gives the name of the undefined variable. On the +other hand, with OP_ADD there are two branches to follow, so we only print +the variable name if we get an exact match. + +The name is returned as a mortal SV. + +Assumes that PL_op is the op that originally triggered the error, and that +PL_comppad/PL_curpad points to the currently executing pad. + + SV* find_uninit_var(OP* obase, SV* uninit_sv, bool top) + +=for hackers +Found in file sv.c + =item report_uninit Print appropriate "Use of uninitialized variable" warning - void report_uninit() + void report_uninit(SV* uninit_sv) =for hackers Found in file sv.c