Skip to content

Commit

Permalink
Use PL_parser->lex_shared instead of Sv[IN]VX(PL_linestr)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Father Chrysostomos committed Aug 28, 2012
1 parent 4730151 commit 60f40a3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 40 deletions.
2 changes: 2 additions & 0 deletions parser.h
Expand Up @@ -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;

Expand Down
1 change: 0 additions & 1 deletion perl.h
Expand Up @@ -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/// */
Expand Down
60 changes: 21 additions & 39 deletions toke.c
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) ) {
Expand Down

0 comments on commit 60f40a3

Please sign in to comment.