This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use PL_parser->lex_shared instead of Sv[IN]VX(PL_linestr)
authorFather Chrysostomos <sprout@cpan.org>
Tue, 28 Aug 2012 08:11:30 +0000 (01:11 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 28 Aug 2012 08:13:17 +0000 (01:13 -0700)
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.

parser.h
perl.h
toke.c

index 16b756f..95083d6 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -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;
 
diff --git a/perl.h b/perl.h
index f4dc00e..7f907df 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -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/// */
diff --git a/toke.c b/toke.c
index f9eec8f..c41a614 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -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)) ) {