my %ignore_op; # Hash of ops which do nothing except returning op_next
my %need_curcop; # Hash of ops which need PL_curcop
+my %lexstate; #state of padsvs at the start of a bblock
+
BEGIN {
foreach (qw(pp_scalar pp_regcmaybe pp_lineseq pp_scope pp_null)) {
$ignore_op{$_} = 1;
}
}
+sub save_or_restore_lexical_state {
+ my $bblock=shift;
+ unless( exists $lexstate{$bblock}){
+ foreach my $lex (@pad) {
+ next unless ref($lex);
+ ${$lexstate{$bblock}}{$lex->{iv}} = $lex->{flags} ;
+ }
+ }else{
+ foreach my $lex (@pad) {
+ next unless ref($lex);
+ my $old_flags=${$lexstate{$bblock}}{$lex->{iv}} ;
+ next if ( $old_flags eq $lex->{flags});
+ if (($old_flags & VALID_SV) && !($lex->{flags} & VALID_SV)){
+ $lex->write_back;
+ }
+ if (($old_flags & VALID_DOUBLE) && !($lex->{flags} & VALID_DOUBLE)){
+ $lex->load_double;
+ }
+ if (($old_flags & VALID_INT) && !($lex->{flags} & VALID_INT)){
+ $lex->load_int;
+ }
+ }
+ }
+}
+
sub write_back_stack {
my $obj;
return unless @stack;
if (@stack >= 1) {
my $bool = pop_bool();
write_back_stack();
+ save_or_restore_lexical_state($$next);
runtime(sprintf("if (!$bool) {XPUSHs(&PL_sv_no); goto %s;}", label($next)));
} else {
+ save_or_restore_lexical_state($$next);
runtime(sprintf("if (!%s) goto %s;", top_bool(), label($next)),
"*sp--;");
}
if (@stack >= 1) {
my $bool = pop_bool @stack;
write_back_stack();
+ save_or_restore_lexical_state($$next);
runtime(sprintf("if (%s) { XPUSHs(&PL_sv_yes); goto %s; }",
$bool, label($next)));
} else {
+ save_or_restore_lexical_state($$next);
runtime(sprintf("if (%s) goto %s;", top_bool(), label($next)),
"*sp--;");
}
reload_lexicals();
my $bool = pop_bool();
write_back_stack();
+ save_or_restore_lexical_state($$false);
runtime(sprintf("if (!$bool) goto %s;", label($false)));
return $op->other;
}
return $op->next;
}
+
sub pp_pushmark {
my $op = shift;
write_back_stack();
# See comment in pp_grepwhile to see why!
$init->add("((LISTOP*)$sym)->op_first = $sym;");
runtime("if (PL_op == ((LISTOP*)($sym))->op_first){");
+ save_or_restore_lexical_state(${$op->first});
runtime( sprintf("goto %s;",label($op->first)));
runtime("}");
return $op->next;
$next->save;
my $nexttonext=$next->next;
$nexttonext->save;
+ save_or_restore_lexical_state($$nexttonext);
runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
label($nexttonext)));
return $op->next->other;
$next->save;
my $nexttonext=$next->next;
$nexttonext->save;
+ save_or_restore_lexical_state($$nexttonext);
runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
label($nexttonext)));
return $op->next->other;
# around that, we hack op_next to be our own op (purely because we
# know it's a non-NULL pointer and can't be the same as op_other).
$init->add("((LOGOP*)$sym)->op_next = $sym;");
+ save_or_restore_lexical_state($$next);
runtime(sprintf("if (PL_op == ($sym)->op_next) goto %s;", label($next)));
$know_op = 0;
return $op->other;
# We need to save our UNOP structure since pp_flop uses
# it to find and adjust out targ. We don't need it ourselves.
$op->save;
+ save_or_restore_lexical_state(${$op->other});
runtime sprintf("if (SvTRUE(PL_curpad[%d])) goto %s;",
$op->targ, label($op->other));
unshift(@bblock_todo, $op->other);
if ($op->flags & OPf_SPECIAL) {
runtime("sv_setiv(PL_curpad[$ix], 1);");
} else {
+ save_or_restore_lexical_state(${$op->first->other});
runtime("\tsv_setiv(PL_curpad[$ix], 0);",
"\tsp--;",
sprintf("\tgoto %s;", label($op->first->other)));
default_pp($op);
my $nextop = $cxstack[$cxix]->{nextop};
push(@bblock_todo, $nextop);
+ save_or_restore_lexical_state($$nextop);
runtime(sprintf("goto %s;", label($nextop)));
return $op->next;
}
default_pp($op);
my $redoop = $cxstack[$cxix]->{redoop};
push(@bblock_todo, $redoop);
+ save_or_restore_lexical_state($$redoop);
runtime(sprintf("goto %s;", label($redoop)));
return $op->next;
}
default_pp($op);
my $lastop = $cxstack[$cxix]->{lastop}->next;
push(@bblock_todo, $lastop);
+ save_or_restore_lexical_state($$lastop);
runtime(sprintf("goto %s;", label($lastop)));
return $op->next;
}
my $sym = doop($op);
my $replroot = $op->pmreplroot;
if ($$replroot) {
+ save_or_restore_lexical_state($$replroot);
runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplroot) goto %s;",
$sym, label($replroot));
$op->pmreplstart->save;
# my $pmopsym = objsym($pmop);
my $pmopsym = $pmop->save; # XXX can this recurse?
# warn "pmopsym = $pmopsym\n";#debug
+ save_or_restore_lexical_state(${$pmop->pmreplstart});
runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplstart) goto %s;",
$pmopsym, label($pmop->pmreplstart));
invalidate_lexicals();
sub compile_bblock {
my $op = shift;
#warn "compile_bblock: ", peekop($op), "\n"; # debug
+ save_or_restore_lexical_state($$op);
write_label($op);
$know_op = 0;
do {
}
init_pp($name);
load_pad(@padlist);
+ %lexstate=();
B::Pseudoreg->new_scope;
@cxstack = ();
if ($debug_timings) {
if (!$$op) {
runtime("PUTBACK;","return PL_op;");
} elsif ($done{$$op}) {
+ save_or_restore_lexical_state($$op);
runtime(sprintf("goto %s;", label($op)));
}
}