diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-08-28 01:11:30 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-08-28 01:13:17 -0700 |
commit | 60f40a389519ab4482a60df44e5e9a03c8710752 (patch) | |
tree | 3655689f6491d244b0fa3b5aa0806206490e5fef | |
parent | 473015163cb5f5f4cc6ef07c71f34b9d6c8608f1 (diff) | |
download | perl-60f40a389519ab4482a60df44e5e9a03c8710752.tar.gz |
Use PL_parser->lex_shared instead of Sv[IN]VX(PL_linestr)
Unfortunately, PL_parser->linestr and PL_parser->bufptr are both
part of the API, so we can’t just move them to PL_parser->lex_shared.
Instead, we have to copy them in sublex_push, to make them visible to
inner lexing scopes.
This allows the SvIVX(PL_linestr) and SvNVX(PL_linestr) hack to
be removed.
It should also speed things up slightly. We are already allocating
PL_parser->lex_shared in sublex_push, so there should be no need to
upgrade PL_linestr to SvNVX as well.
I was pleasantly surprised to see how the here-doc code seemed to
shrink all by itself when modified to account.
PL_sublex_info.super_bufptr is also superseded by the addition of
->ls_bufptr to the LEXSHARED struct. Its old values when localised
were not visible, being stashed away on the savestack, so it was
harder to use.
-rw-r--r-- | parser.h | 2 | ||||
-rw-r--r-- | perl.h | 1 | ||||
-rw-r--r-- | toke.c | 60 |
3 files changed, 23 insertions, 40 deletions
@@ -25,6 +25,8 @@ typedef struct { ing scopes. */ typedef struct yy_lexshared { struct yy_lexshared *ls_prev; + SV *ls_linestr; /* mirrors PL_parser->linestr */ + char *ls_bufptr; /* mirrors PL_parser->bufptr */ line_t herelines; /* number of lines in here-doc */ } LEXSHARED; @@ -3456,7 +3456,6 @@ struct _sublex_info { U8 super_state; /* lexer state to save */ U16 sub_inwhat; /* "lex_inwhat" to use */ OP *sub_op; /* "lex_op" to use */ - char *super_bufptr; /* PL_parser->bufptr that was */ char *re_eval_start;/* start of "(?{..." text */ SV *re_eval_str; /* "(?{...})" text */ SV *repl; /* replacement of s/// or y/// */ @@ -2473,7 +2473,6 @@ S_sublex_push(pTHX) SAVESPTR(PL_lex_repl); SAVEPPTR(PL_sublex_info.re_eval_start); SAVESPTR(PL_sublex_info.re_eval_str); - SAVEPPTR(PL_sublex_info.super_bufptr); SAVEVPTR(PL_lex_inpat); SAVEI16(PL_lex_inwhat); SAVECOPLINE(PL_curcop); @@ -2490,24 +2489,11 @@ S_sublex_push(pTHX) SAVEGENERICPV(PL_parser->lex_shared); /* The here-doc parser needs to be able to peek into outer lexing - scopes to find the body of the here-doc. We use SvIVX(PL_linestr) - to store the outer PL_bufptr and SvNVX to store the outer - PL_linestr. Since SvIVX already means something else, we use - PL_sublex_info.super_bufptr for the innermost scope (the one we are - now entering), and a localised SvIVX for outer scopes. + scopes to find the body of the here-doc. So we put PL_linestr and + PL_bufptr into lex_shared, to ‘share’ those values. */ - SvUPGRADE(PL_linestr, SVt_PVIV); - /* A null super_bufptr means the outer lexing scope is not peekable, - because it is a single line from an input stream. */ - SAVEIV(SvIVX(PL_linestr)); - SvIVX(PL_linestr) = PTR2IV(PL_sublex_info.super_bufptr); - PL_sublex_info.super_bufptr = - (SvTYPE(PL_linestr) < SVt_PVNV || !SvNVX(PL_linestr)) - && (PL_rsfp || PL_parser->filtered) - ? NULL - : PL_bufptr; - SvUPGRADE(PL_lex_stuff, SVt_PVNV); - SvNVX(PL_lex_stuff) = PTR2NV(PL_linestr); + PL_parser->lex_shared->ls_linestr = PL_linestr; + PL_parser->lex_shared->ls_bufptr = PL_bufptr; PL_linestr = PL_lex_stuff; PL_lex_repl = PL_sublex_info.repl; @@ -2575,8 +2561,6 @@ S_sublex_done(pTHX) /* Is there a right-hand side to take care of? (s//RHS/ or tr//RHS/) */ assert(PL_lex_inwhat != OP_TRANSR); if (PL_lex_repl && (PL_lex_inwhat == OP_SUBST || PL_lex_inwhat == OP_TRANS)) { - SvUPGRADE(PL_lex_repl, SVt_PVNV); - SvNVX(PL_lex_repl) = SvNVX(PL_linestr); PL_linestr = PL_lex_repl; PL_lex_inpat = 0; PL_bufend = PL_bufptr = PL_oldbufptr = PL_oldoldbufptr = PL_linestart = SvPVX(PL_linestr); @@ -9657,33 +9641,31 @@ S_scan_heredoc(pTHX_ register char *s) bufptr. See the comments in sublex_push for how IVX and NVX are abused. */ - SV *linestr = NUM2PTR(SV *, SvNVX(PL_linestr)); - char *bufptr = PL_sublex_info.super_bufptr; - char *bufend = SvEND(linestr); + SV *linestr; + char *bufptr, *bufend; char * const olds = s - SvCUR(herewas); char * const real_olds = s; PERL_CONTEXT * const cx = &cxstack[cxstack_ix]; - shared = shared->ls_prev; - if (!bufptr) { - s = real_olds; - goto streaming; - } - while (!(s = (char *)memchr((void *)bufptr, '\n', bufend-bufptr))){ - if (SvIVX(linestr)) { - bufptr = INT2PTR(char *, SvIVX(linestr)); - linestr = NUM2PTR(SV *, SvNVX(linestr)); - bufend = SvEND(linestr); - shared = shared->ls_prev; - } - else if (infile) { + do { + shared = shared->ls_prev; + /* A LEXSHARED struct with a null ls_prev pointer is the outer- + most lexing scope. In a file, shared->ls_linestr at that + level is just one line, so there is no body to steal. */ + if (infile && !shared->ls_prev) { s = real_olds; goto streaming; } - else { - s = bufend; + else if (!shared) { + s = SvEND(shared->ls_linestr); break; } - } + } while (!(s = (char *)memchr( + (void *)shared->ls_bufptr, '\n', + SvEND(shared->ls_linestr)-shared->ls_bufptr + ))); + bufptr = shared->ls_bufptr; + linestr = shared->ls_linestr; + bufend = SvEND(linestr); d = s; while (s < bufend && (*s != '\n' || memNE(s,PL_tokenbuf,len)) ) { |