Make constant folding use the right hints
authorFather Chrysostomos <sprout@cpan.org>
Fri, 9 Aug 2013 21:24:23 +0000 (14:24 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 10 Aug 2013 02:44:13 +0000 (19:44 -0700)
commita547fd219bacc248099bb2b7f606cc120cce2c71
treefcb3b386a88656d7e4b27113a21dd36ca9738786
parentd36ee5be0c1466cc557c9d9f328896dc96483962
Make constant folding use the right hints

This was brought up in ticket #117855.

PL_compiling is a cop-sized static buffer (inside the interpreter
struct under threads) that stores information during compile time
(such as file name and line number) that gets copied to each cop (con-
trol op; aka state op or nextstate op) as it is created.

Some values are not actually stored in PL_compiling, such as the
current stash (PL_curstash is used instead) and the current hints
(PL_hints is used).

The ops in each statement are created before that statement’s cop
is created.

At run time, each cop is executed at the start of the statement and
sets PL_curcop to point to itself, so that operators within that
statement can get information from PL_curcop.

Constant folding was copying the contents of PL_compiling into a tem-
porary cop used to execute the ops being folded.  That constant fold-
ing happened of course before the cop was created for that statement.

Now it just happened that commit a0ed51b321 back in 1998 modified
newSTATEOP to copy hints to PL_compiling in addition to the new cop
being created.  Presumably that was to fix the type of bug that this
commit is addressing.  (Presumably this commit renders those changes
unnecessary.)  That meant that most of the time constant folding would
see the right hints.

That fails, though, when it comes to the first statement in a string
eval.  When you do eval("uc(ä)"), the constant folding happens when
PL_compiling.cop_hints still points to whatever value it had before
the eval was executed; i.e., an unpredictable value.  Slight changes
to unrelated scopes (and, apparently, using a different compiler*) can
cause the result of that string eval to change.

The solution is to set the hints from PL_hints explicitly when doing
constant folding.

* <https://rt.perl.org/rt3/Ticket/Display.html?id=117855#txn-1241613>ff.
  I never got to the bottom of why the compiler would make a diffe-
  rence here.  Finding out would involve setting a watchpoint on
  PL_compiling.cop_hints in a C debugger and then stepping through
  the thousands of times PL_compiling changes, which is too much
  work.  Nevertheless, I know this fix is correct, as it changes
  PL_compiling.cop_hints from having a non-deterministic value during
  constant folding to having a predictable one.
op.c
t/op/lc.t