summaryrefslogtreecommitdiff
path: root/op.h
Commit message (Collapse)AuthorAgeFilesLines
* add wrap_op_checker() API functionZefram2012-02-111-0/+16
| | | | | This function provides a convenient and thread-safe way for modules to hook op checking.
* [perl #77388] Make stacked -t workFather Chrysostomos2012-01-231-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Up till now, -t was popping too much off the stack when stacked with other filetest operators. Since the special use of _ doesn’t apply to -t, we cannot simply have it use _ when stacked, but instead we pass the argument down from the previous op. To facilitate this, the whole stacked mechanism has to change. As before, in an expression like -r -w -x, -x and -w are flagged as ‘stacking’ ops (followed by another filetest), and -w and -r are flagged as stacked (preceded by another filetest). Stacking filetest ops no longer return a false value to the next op when a test fails, and stacked ops no longer check the truth of the value on the stack to determine whether to return early (if it’s false). The argument to the first filetest is now passed from one op to another. This is similar to the mechanism that overloaded objects were already using. Now it applies to any argument. Since it could be false, we cannot rely on the boolean value of the stack item. So, stacking ops, when they return false, now traverse the ->op_next pointers and find the op after the last stacked op. That op is returned to the runloop. This short-circuiting is proba- bly faster than calling every subsequent op (a separate function call for each). Filetest ops other than -t continue to use the last stat buffer when stacked, so the argument on the stack is ignored. But if the op is preceded by nothing other than -t (where preceded means on the right, since the ops are evaluated right-to-left), it *does* use the argument on the stack, since -t has not set the last stat buffer. The new OPpFT_AFTER_t flag indicates that a stacked op is preceded by nothing other than -t. In ‘-e -t foo’, the -e gets the flag, but not in ‘-e -t -r foo’, because -r will have saved the stat buffer, so -e can just use that.
* Stop tell($glob_copy) from clearing PL_last_in_gvFather Chrysostomos2011-12-171-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This bug is a side effect of rv2gv’s starting to return an incoercible mortal copy of a coercible glob in 5.14: $ perl5.12.4 -le 'open FH, "t/test.pl"; $fh=*FH; tell $fh; print tell' 0 $ perl5.14.0 -le 'open FH, "t/test.pl"; $fh=*FH; tell $fh; print tell' -1 In the first case, tell without arguments is returning the position of the filehandle. In the second case, tell with an explicit argument that happens to be a coercible glob (tell has an implicit rv2gv, so tell $fh is actu- ally tell *$fh) sets PL_last_in_gv to a mortal copy thereof, which is freed at the end of the statement, setting PL_last_in_gv to null. So there is no ‘last used’ handle by the time we get to the tell without arguments. This commit adds a new rv2gv flag that tells it not to copy the glob. By doing it unconditionally on the kidop, this allows tell(*$fh) to work the same way. Let’s hope nobody does tell(*{*$fh}), which will unset PL_last_in_gv because the inner * returns a mortal copy. This whole area is really icky. PL_last_in_gv should be refcounted, but that would cause handles to leak out of scope, breaking programs that rely on the auto-closing ‘feature’.
* [perl #91514] Use correct error msg for defaultFather Chrysostomos2011-12-161-1/+2
| | | | | | | | This commit not only mentions default (as opposed to when) in the error message about it being outside a topicalizer, but also normalises those error messages, making them consistent with continue and other loop controls. It also makes the perldiag entry for when actually match the error message.
* Optimise substr assignment in void contextFather Chrysostomos2011-11-261-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In void context we can optimise substr($foo, $bar, $baz) = $replacement; to something like substr($foo, $bar, $baz, $replacement); except that the execution order must be preserved. So what we actu- ally do is substr($replacement, $foo, $bar, $baz); with a flag to indicate that the replacement comes first. This means we can also optimise assignment to two-argument substr the same way. Although optimisations are not supposed to change behaviour, this one does. • It stops substr assignment from calling get-magic twice, which means the optimisation makes things less buggy than usual. • It causes the uninitialized warning (for an undefined first argu- ment) to mention the substr operator, as it did before the previous commit, rather than the assignment operator. I think that sort of detail is minor enough. I had to make the warning about clobbering references apply whenever substr does a replacement, and not only when used as an lvalue. So four-argument substr now emits that warning. I would consider that a bug fix, too. Also, if the numeric arguments to four-argument substr and the replacement string are undefined, the order of the uninitialized warn- ings is slightly different, but is consistent regardless of whether the optimisation is in effect. I believe this will make 95% of substr assignments run faster. So there is less incentive to use what I consider the less readable form (the four-argument form, which is not self-documenting). Since I like naïve benchmarks, here are Before and After: $ time ./miniperl -le 'do{$x="hello"; substr ($x,0,0) = 34;0}for 1..1000000' real 0m2.391s user 0m2.381s sys 0m0.005s $ time ./miniperl -le 'do{$x="hello"; substr ($x,0,0) = 34;0}for 1..1000000' real 0m0.936s user 0m0.927s sys 0m0.005s
* [perl #80628] __SUB__Father Chrysostomos2011-11-221-1/+1
| | | | | After much alternation, altercation and alteration, __SUB__ is finally here.
* Add evalbytes functionFather Chrysostomos2011-11-061-0/+2
| | | | | | | | | | | This function evaluates its argument as a byte string, regardless of the internal encoding. It croaks if the string contains characters outside the byte range. Hence evalbytes(" use utf8; '\xc4\x80' ") will return "\x{100}", even if the original string had the UTF8 flag on, and evalbytes(" '\xc4\x80' ") will return "\xc4\x80". This has the side effect of fixing the deparsing of CORE::break under ‘use feature’ when there is an override.
* eval STRING UTF8 cleanup.Brian Fraser2011-11-061-0/+1
| | | | | (modified by the committer only to apply when the unicode_eval feature is enabled)
* Fix CORE::globFather Chrysostomos2011-10-261-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | This commit makes CORE::glob bypassing glob overrides. A side effect of the fix is that, with the default glob implementa- tion, undefining *CORE::GLOBAL::glob no longer results in an ‘unde- fined subroutine’ error. Another side effect is that compilation of a glob op no longer assumes that the loading of File::Glob will create the *CORE::GLOB::glob type- glob. ‘++$INC{"File/Glob.pm"}; sub File::Glob::csh_glob; eval '<*>';’ used to crash. This is accomplished using a mechanism similar to lock() and threads::shared. There is a new PL_globhook interpreter varia- ble that pp_glob calls when there is no override present. Thus, File::Glob (which is supposed to be transparent, as it *is* the built-in implementation) no longer interferes with the user mechanism for overriding glob. This removes one tier from the five or so hacks that constitute glob’s implementation, and which work together to make it one of the buggiest and most inconsistent areas of Perl.
* Oust cv_ckproto_lenFather Chrysostomos2011-10-061-1/+1
| | | | | | | | | | It is no longer used in core (having been superseded by cv_ckproto_len_flags), is unused on CPAN, and is not part of the API. The cv_ckproto ‘public’ macro is modified to use the _flags version. I put ‘public’ in quotes because, even before this commit, cv_ckproto was using a non-exported function, and hence could never have worked on a strict linker (or whatever you call it).
* Groundwork to allow cops and pmops to store the UTF8 flagBrian Fraser2011-10-061-7/+18
| | | | | | | | | With threaded builds, cop.h and op.h get an extra member in their structs, to save the UTF-8ness of the stash's name. *STASH_set() checks for the flag, stores it through *STASH_flags(), and *STASH() uses the latter to fetch the correct scalar.
* remove index offsetting ($[)Zefram2011-09-091-1/+0
| | | | | | $[ remains as a variable. It no longer has compile-time magic. At runtime, it always reads as zero, accepts a write of zero, but dies on writing any other value.
* Use OPpDEREF for lvalue sub, such that the flags contains the deref type, ↵Gerard Goossen2011-09-011-1/+1
| | | | | | | instead of deriving it from the opchain. Also contains a test where using the opchain to determine the deref type fails.
* Reassign op_private flags of OP_ENTERSUB such that bits 32 and 64 can be ↵Gerard Goossen2011-09-011-3/+3
| | | | used by OPpDEREF
* Add OPpCOREARGS_SCALARMOD flagFather Chrysostomos2011-08-261-0/+1
| | | | | pp_coreargs will use this to distinguish between the \$ and \[$@%*] prototypes.
* Add OPpCOREARGS_PUSHMARK flagFather Chrysostomos2011-08-251-0/+1
| | | | | | | | | This will be used to tell pp_coreargs when it needs to call pp_pushmark. For those functions that need a pushmark, it has to come between two things that pp_coreargs does; so the easiest way is to use this flag.
* Add private coreargs flags for vivifying GVsFather Chrysostomos2011-08-251-0/+5
|
* [perl #97088] Prevent double get-magic in various casesGerard Goossen2011-08-241-2/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch prevents get-magic from executing twice during autovivifi- cation when the op doing the autovivification is not directly nested inside the dereferencing op. This can happen in cases like this: ${ (), $a } = 1; Previously (as of 5.13.something), the outer op was marked with the OPpDEREFed flag, which indicated that get-magic had already been called by the vivifying op (calling get-magic during vivification is inevitable): $ perl5.14.0 -MO=Concise -e '${ $a } = 1' 8 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 2 -e:1) v:{ ->3 7 <2> sassign vKS/2 ->8 3 <$> const[IV 1] s ->4 6 <1> rv2sv sKRM*/DREFed,1 ->7 <-- right here - <@> scope sK ->6 - <0> ex-nextstate v ->4 5 <1> rv2sv sKM/DREFSV,1 ->6 4 <#> gv[*a] s ->5 -e syntax OK But in the ${()...} example above, there is a list op in the way that prevents the flag from being set inside the peephole optimizer. It’s not even possible to set it correctly in all cases, as in this exam- ple, which would need it both set and not set depending on which branch of the ternary operator is executed: ${ $x ? delete $a[0] : $a[0] } = 1 Instead of setting the OPpDEREFed flag, we now make a non-magic copy of the SV in vivify_ref (the first time get-magic is executed).
* &CORE::wantarray()Father Chrysostomos2011-08-181-0/+3
| | | | | | | | This commit allows &CORE::wantarray to be called via ampersand syntax or through references. It adds a new private flag for wantarray, OPpOFFBYONE, which caller will use as well, telling wantarray (or caller) to look one call fur- ther up the call stack.
* Remove OPpENTERSUB_NOMOD.Gerard Goossen2011-08-151-1/+0
| | | | | | OPpENTERSUB_NOMOD was always set in combination with OPf_WANT_VOID which is now used to not propagate the lvalue context, making OPpENTERSUB_NOMOD redundant.
* Improve comments about op_private bits. And move the non op specific flags ↵Gerard Goossen2011-08-141-4/+8
| | | | to the top.
* use a flag to signal a stacking filetests instead of peeking at the next op.Gerard Goossen2011-07-111-1/+2
| | | | Preparation for the codegeneration changes where the next op isn't accessible.
* Propagate (non-)lvalue context through nested callsFather Chrysostomos2011-07-091-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Before this commit, this code would fail: $foo = "foo"; sub foo :lvalue{ return index "foo","o" } sub bar :lvalue { foo } $x = bar; (It would fail for ‘return $]’ as well. Whether it’s a PADTMP or a read-only scalar makes no difference.) foo would think it was being called in true lvalue context, because the entersub op that called it (in bar) was marked that way, bar being an lvalue sub as well. The PUSHSUB macro in cop.h needed to be modified to account for dynamic, or indetermine, context (i.e., indeterminable at compile time). This happens when an entersub op is an argument to return or the last statement in a subroutine. In those cases it has to propa- gate the context from the caller. So what we now do is this: Both lvalue and in-args flags are turned on for an entersub op when op_lvalue is called with OP_LEAVESUBLV as the type. Then PUSHSUB copies into the context stack only those flags that are set both on the current entersub op and in the context stack for the previous sub call.
* Fix context propagation below return()Vincent Pit2011-06-271-1/+0
| | | | | | | | | | | | | A.k.a. "RT #38809 strikes back". Back in the time of perl 5.003, there was no void context, so "do" blocks below a return needed special handling to use the dynamic context of the caller instead of the static context implied by the return op location. But nowadays context is applied by the scalarvoid(), scalar() and list() functions, and they all already skip the return ops. "do" blocks below a return don't get a static context, and GIMME_V ought to correctly return the caller's context. The old workaround isn't even required anymore.
* Correctly preserve the stack on an implicit break.Vincent Pit2011-06-261-1/+0
| | | | | | | | | | | | | | | | | | | | | | Perl generates a 'break' op with the special flag set at the end of every 'when' block. This makes it difficult to handle both the case of an implicit break, where the stack has to be preserved, and the case of an explicit break, which must obliterate the stack, with the same pp function. Stack handling should naturally occur in 'leavewhen', but it is effectively called only when the block issues a 'continue'. In order to preserve the stack, we change the respective roles of 'break', 'continue' and 'leavewhen' ops : - Special 'break' ops are no longer generated for implicit breaks. Just as before, they give the control back to the 'leavegiven' op. - 'continue' ops now directly forward to the op *following* the 'leavewhen' op of the current 'when' block. - 'leavewhen' is now only called at the natural end of a 'when' block. It adjusts the stack to make sure returned values survive the temp cleanup, then issues a 'next' or go to the current 'leavegiven' depending on whether it is enclosed in a for loop or a given block. This fixes [perl #93548].
* Correct comment that 903fd87c missedFather Chrysostomos2011-06-241-1/+1
|
* Make Perl_op_lvalue_flags provide a no-croak optionFather Chrysostomos2011-06-241-0/+4
| | | | This is in preparation for making the \$ prototype accept any lvalue.
* op_lvalue .= _flagsFather Chrysostomos2011-06-241-0/+2
| | | | | | | | | | Add flags param to op_lvalue, so that the caller can ask it not to croak when encountering an unmodifiable op (upcoming). This is in preparation for making the \$ prototype accept any lvalue. There is no mathom, as the changes that this will support are by no means suitable for maint.
* Split OP_AELEMFAST_LEX out from OP_AELEMFAST.Nicholas Clark2011-06-121-1/+0
| | | | | | | | | | | | | 6a077020aea1c5f0 extended the OP_AELEMFAST optimisation to lexical arrays. Previously OP_AELEMFAST was only used as an optimisation for OP_GV, which is a PADOP/SVOP. However, by reusing the same opcode, and signalling (pad) lexical vs package, it introduced a myriad of special cases, because OP_PADAV is a BASEOP (not a PADOP), whilst OP_AELEMFAST is a PADOP/SVOP (which is larger). Using two OP numbers allows each variant to have the correct OP flags in PL_opargs. Both can continue to share the same C code.
* In B::Concise and op.h list all ops that use LVSUBFather Chrysostomos2011-06-091-1/+2
| | | | keys doesn’t actually use it yet, but it will soon.
* [perl #7946] Lvalue subs do not autovivifyFather Chrysostomos2011-06-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit makes autovivification work with lvalue subs. It follows the same technique used by other autovivifiable ops (aelem, helem, tc.), except that, due to flag constraints, it uses a single flag and instead checks the op tree at run time to find out what sort of thing to vivify. The flag constraints are that these two flags: #define OPpENTERSUB_HASTARG 32 /* Called from OP tree. */ #define OPpENTERSUB_NOMOD 64 /* Immune to op_lvalue() for :attrlist. */ conflict with these: #define OPpDEREF (32|64) /* autovivify: Want ref to something: */ #define OPpDEREF_AV 32 /* Want ref to AV. */ #define OPpDEREF_HV 64 /* Want ref to HV. */ #define OPpDEREF_SV (32|64) /* Want ref to SV. */ Renumbering HASTARG and NOMOD is problematic, as there are places in op.c that change entersubs into rv2cvs, and the entersub and rv2cv flags would conflict. Setting the flags correctly when changing the type is hard and would result in subtle bugs if not done perfectly. Ops like ${...} don’t actually autovivify; it’s the op inside that does it. In those cases, the parent op is flagged with OPpDEREFed, and it skips get-magic, as it has already been called by the inner op. Since entersub is now marked as being an autovivifying op, ${...} in lvalue context ends up skipping get-magic if there is a foo() inside. And this affects even regular subs. So pp_leavesub and pp_return have to call get-magic; hence the new tests in gmagic.t.
* Rearrange some private op flag constantsFather Chrysostomos2011-06-031-5/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some constants in op.h were a bit muddled up and were not grouped according to which ops used them. And one of the comments was wrong. The history is a bit involved: Commit 7a52d87 added this comment, which was correct: + /* OP_RV2CV only */ #define OPpENTERSUB_AMPER 8 /* Used & form to call. */ Commit 9675f7a added this constant: /* OP_RV2CV only */ #define OPpENTERSUB_AMPER 8 /* Used & form to call. */ +#define OPpENTERSUB_NOPAREN 128 /* bare sub call (without parens) */ Commit cd06dff added this one, which is confusing, as it is only used on entersub: /* OP_RV2CV only */ #define OPpENTERSUB_AMPER 8 /* Used & form to call. */ #define OPpENTERSUB_NOPAREN 128 /* bare sub call (without parens) */ +#define OPpENTERSUB_INARGS 4 /* Lval used as arg to a sub. */ Commit e26df76 added this, resulting in there being two OP_RV2CV sections: + /* OP_RV2CV only */ +#define OPpMAY_RETURN_CONSTANT 1 /* If a constant sub, return the constant */ + To top it all, commit b900987 unfortunately ‘fixed’ a mislead- ing comment: - /* OP_RV2CV only */ + /* OP_ENTERSUB and OP_RV2CV only */ #define OPpENTERSUB_AMPER 8 /* Used & form to call. */ #define OPpENTERSUB_NOPAREN 128 /* bare sub call (without parens) */ #define OPpENTERSUB_INARGS 4 /* Lval used as arg to a sub. */
* document how tainting works with pattern matchingDavid Mitchell2011-02-161-1/+1
|
* Initial setup to accommodate /aa regex modifierKarl Williamson2011-02-141-1/+1
| | | | | This changes the bits to add a new charset type for /aa, and other bookkeeping for it.
* op.h: add blank line for groupingKarl Williamson2011-01-161-0/+1
|
* Fix typos (spelling errors) in Perl sources.Peter J. Acklam) (via RT2011-01-071-2/+2
| | | | | | | | | # New Ticket Created by (Peter J. Acklam) # Please include the string: [perl #81904] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=81904 > Signed-off-by: Abigail <abigail@abigail.be>
* call pp_glob() even when its being skippedDavid Mitchell2011-01-021-0/+1
| | | | | | | | | | | | | | Currently when an external Perl glob function is used (which is most of the time), the OP_GLOB op is removed and replaced with the pair: GV("CORE::GLOBAL::glob"), ENTERSUB. This commit re-adds the OP_GLOB to the op tree, but with OPf_SPECIAL set; and pp_glob() is updated to just return if OPf_SPECIAL is set. Thus there's no change in outward functionality with this commit. However, by always calling pp_glob(), it will allow us (in the next commit) to handle iterator overloading consistently, regardless of whether the internal globbing function is used or not.
* mark blockhooks API as experimentalZefram2010-12-131-6/+6
|
* [perl #77762] Constant assignment warningFather Chrysostomos2010-11-301-0/+1
| | | | | | | | | | | | With this patch: $ ./perl -we 'sub A () {1}; if (0) {my $foo = A or die}' $ ./perl -we 'sub A () {1}; if (0) {my $foo = 1 or die}' Found = in conditional, should be == at -e line 1. Since the value of a constant may not be known at the time the program is written, it should be perfectly acceptable to do a constant assign- ment in a conditional.
* Convert newSUB() to a macro wrapping Perl_newATTRSUB()Nicholas Clark2010-11-171-0/+2
| | | | | Provide a Perl_newSUB() function in mathoms.c for anyone referencing it by its full name.
* Document the new custom op functions.Ben Morrow2010-11-141-0/+46
|
* Improve custom OP support.Ben Morrow2010-11-141-0/+46
| | | | | | | | | | | | | | | | | Change the custom op registrations from two separate hashes to one hash holding structure pointers, and add API functions to register ops and look them up. This will make it easier to add new properties of custom ops in the future. Copy entries across from the old hashes where necessary, to preserve compatibility. Add two new properties, in addition to the already-existing 'name' and 'description': 'class' and 'peep'. 'class' is one of the OA_*OP constants, and allows B and other introspection mechanisms to work with custom ops that aren't BASEOPs. 'peep' is a pointer to a function that will be called for ops of this type from Perl_rpeep. Adjust B.xs to take account of the new properties, and also to give custom ops their registered name rather than simply 'custom'.
* Remove THREADSV_NAMES, part of 5005 threads that the chainsaw missed.Nicholas Clark2010-10-271-1/+0
| | | | | Also remove the documentation of OPf_SPECIAL for OP_ENTERITER, as that was only for 5.005 threads. Stop B::Deparse misinterpreting OPf_SPECIAL on OP_ENTERITER.
* new API functions op_scope and op_lvalueZefram2010-10-261-1/+1
| | | | | | The function scope() goes into the API as op_scope(), and mod() goes into the API as op_lvalue(). Both marked experimental, because their behaviour is a little quirky and not trivially dequirkable.
* Add LINKLIST to the API.Ben Morrow2010-10-121-0/+15
| | | | | Also rename the underlying function to op_linklist, to match the other API op functions.
* Remove some excess cleverness from the Bhk macros.Ben Morrow2010-10-101-6/+6
| | | | | | | | | Allowing BhkENTRY(bhk, start) to look up the bhk_start member defeats much of the point of having a bhk_ prefix in the first place: if a member is added later called (say) 'bhk_die', any invocation of BhkENTRY(bhk, die) will expand to BhkENTRY(bhk, Perl_die) because of the API macros. Requiring BhkENTRY(bhk, bhk_start), while tedious, is much safer.
* plugin mechanism to rewrite calls to a subroutineZefram2010-10-101-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | New magic type PERL_MAGIC_checkcall attaches a function to a CV, which will be called as the second half of the op checker for an entersub op calling that CV. Default state, in the absence of this magic, is to process the CV's prototype if it has one, or apply list context to all the arguments if not. New API functions cv_get_call_checker() and cv_set_call_checker() provide a clean interface to this facility, hiding the internal use of magic. Expose in the API the new functions rv2cv_op_cv(), ck_entersub_args_list(), ck_entersub_args_proto(), and ck_entersub_args_proto_or_list(), which are meaningful segments of standard entersub op checking and are likely to be useful in plugged-in call checker functions. Expose new API function op_contextualize(), which is a public interface to the internal scalar()/list()/scalarvoid() functions. This API is likely to be required in most plugged-in call checker functions. Incidentally add new function mg_free_type(), in the API, which will remove magic of one type from an SV. (mg_free() removes all magic, and there isn't anything else more selective.)
* Add /d, /l, /u (infixed) regex modifiersKarl Williamson2010-09-221-1/+1
| | | | | | | | | | | | This patch adds recognition of these modifiers, with appropriate action for d and l. u does nothing useful yet. This allows for the interpolation of a regex into another one without losing the character set semantics that it was compiled with, as for the first time, the semantics is now specified in the stringification as one of these modifiers. To this end, it allocates an unused bit in the structures. The off- sets change so as to not disturb other bits.
* [perl #20444] regex not evaluated in constant ?:Father Chrysostomos2010-09-201-0/+4
| | | | | | | | | | | | $text =~ ( 1 ? /phoo/ : /bear/) used to be constant-folded to $text =~ /phoo/ This patch solves the problem by marking match and subst ops as OPf_SPECIAL during constant folding, so the =~ operator can tell not to take possession of it.
* Remove OA_RETINTEGER, unused since 2002 (commit e7311069df54baa6)Nicholas Clark2010-08-281-4/+3
| | | | | | | | This returns us to 8 flag bits, and restores OCSHIFT and OASHIFT to 8 and 12 Previously these were 9 and 13, and effectively PL_opargs[] was using 33 of 32 bits, relying on the ugly hack that no 5 argument builtin had an optional 5th argument, hence the (13 + 5 * 4)th bit was always zero. is effectively 33 bits.