summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-08-28 01:11:30 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-08-28 01:13:17 -0700
commit60f40a389519ab4482a60df44e5e9a03c8710752 (patch)
tree3655689f6491d244b0fa3b5aa0806206490e5fef
parent473015163cb5f5f4cc6ef07c71f34b9d6c8608f1 (diff)
downloadperl-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.h2
-rw-r--r--perl.h1
-rw-r--r--toke.c60
3 files changed, 23 insertions, 40 deletions
diff --git a/parser.h b/parser.h
index 16b756f7f0..95083d6e63 100644
--- 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 f4dc00eba7..7f907df006 100644
--- 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 f9eec8f626..c41a614c18 100644
--- 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)) ) {