James E Keenan [Tue, 2 Nov 2021 23:13:39 +0000 (23:13 +0000)]
Make the expected() utility more closely match context_info()
context_info() returns $warnings::Bits{all} when the warnings for
a context is pWARN_ALL, while caller() returns WARN_ALLstring.
The test tried to avoid loading any modules that registered
warning categories to avoid this making a difference, but
DynaLoader is needed to load Scope::Upper, and DynaLoader uses
vars.pm which registers a warnings category.
This wasn't a problem when the default warning mask wasn't used up to a
byte boundary, but adding the experimental category in Perl 5 commit 3b54923c did align the warning mask on a byte boundary, leading to this
test failing.
Specifically, handle case where warnings mask contains only "\x55"
bytes. Return $warnings::Bits{all} in that case. As suggested by Tony
Cook in: https://rt.cpan.org/Ticket/Display.html?id=139823
BBC ticket: https://github.com/Perl/perl5/issues/19212
Most of commit message suggested by Tony Cook in:
https://github.com/jkeenan/p5-Scope-Upper/pull/1#issuecomment-968375955
Vincent Pit [Sun, 26 Aug 2018 19:08:19 +0000 (21:08 +0200)]
Always apply localizations at the glob level
"localize '$x', $var" used to dereference $var and apply the localization
to $x directly. This did not set the IMPORTED flag on *x when necessary.
In order to fix this, we now follow the opposite logic : $var is now
referenced when the localization target is a scalar, and that reference is
assigned to *x so that localize now really behaves like "local *x = $var".
David Mitchell [Sun, 29 May 2016 21:20:40 +0000 (22:20 +0100)]
fixup t/13-reap-ctl.t for 5.23.8
One test in this script failed under 5.23.8 due to a change in the way
the die while leaving an eval scope is now handled.
Consider the following code, where leaving an eval scope triggers a call
to STORE to unlocalise a tied scalar, and where STORE raises an exception:
sub TIESCALAR { bless [] }
sub FETCH { 1; }
sub STORE { die "died in store\n" if $_[1] }
tie $s, 'main';
eval {
local $s;
};
warn "caught: [$@]\n";
5.23.7 and earlier die, while 5.23.8 output:
caught: [died in store
]
Similarly, one would expect the behaviour of "reap HERE" to change
in 5.23.8, with an exception raised in the reap handler to now be caught
be the innermost eval.
David Mitchell [Sun, 29 May 2016 21:06:38 +0000 (22:06 +0100)]
eliminate CX_ARGARRAY() and CX_ARGARRAY_set()
I added these earlier as a way of compiling the code under both 5.23.7 and
5.23.8, since the latter no longer has the argarray field in the context
struct. I didn't know at the time whether they were logically correct
under 5.23.8 - I just wanted the code to compile.
Having now properly fixed uplevel() to work on 5.23.8, and since uplevel
under 5.23.8 uses an entirely separate code path, only 5.23.7 and earlier
make use of CX_ARGARRAY() and _set(), so eliminate these macros and
revert back to the original usage (i.e. cx->blk_sub.argarray).
David Mitchell [Tue, 17 May 2016 08:23:00 +0000 (09:23 +0100)]
fix uplevel() under 5.23.8+
The old method of creating a new curstackinfo containing the faked-up
new context stack no longer works. This is because leave_scope() is now
called just prior to each context stack entry popping, and so a destructor
which restores the old context array leaves a dangling pointer.
E.g. pp_leavesub() on 5.23.8 onwards looks something like:
cx = CX_CUR();
....
CX_LEAVE_SCOPE(cx);
/* at this point the destructor has been called and the old context
* stack back been restored; cx now points at freed garbage
*/
cx_popsub(cx); /* SEGV */
Conversely, now that it's guaranteed that the save stack is always
processed prior to each context pop - regardless of whether its a normal
scope exit or an exception - it allows us to use a simpler method to fake
things up for uplevel(): just temporarily change the types of all the
higher contexts to CXt_NULL so that they won't be seen by caller() etc. On
scope exit the savestack destructor restores the old types, which are then
processed and popped as normal.
As well as setting each entry to CXt_NULL we set a flag,
CXp_SU_UPLEVEL_NULLED (whose bit is currently unused by the perl core)
to indicate that this is a temporarily ignored context.
We then introduce a distinction between logical and physical context stack
indices: functions like UP return a logical index which ignore all the
nulled-out contexts; when such a logical value is passed as an arg to a
function such as localize(), it is first converted back to a real index.
The other main change is how uplevel() doctors the sub's arg list as seen
by caller(): previously this was done by modifying the argarray field of
the context entry for the just-called sub. Since 5.23.8 onwards doesn't
have an argarray field, we instead modify the pad[0] of the running sub
(which is what caller() examines now). Since there's no longer a
possibility of getting argarray and pad[0] out of sync, the special fixups
formerly required in the presence of goto are no longer required.
Rather than rolling our own OP_ENTERSUB op, we just use call_sv()
instead, with a PL_runops pointing to a temporary hook that allows the
args to be fixed up on return from pp_entersub. After that, a normal
runops loop is called.
Since uplevel is so different under 5.23.8, I've split the original
functions into
David Mitchell [Thu, 19 May 2016 11:03:48 +0000 (12:03 +0100)]
su_uplevel: populate lower stack frames properly
When creating a temporary new argument stack, su_uplevel() copies most of
the old stack to a new one. This isn't really needed, as the new stack
will be abandoned before it ever pops back to that level. But it *is*
needed when debugging code prints out the stack, as in for example,
'perl -Dstv'.
However, the code didn't actually copy the old stack: it copied garbage
instead, since it was using PL_curstack rather than AvARRAY(PL_curstack)
as the address of of the old stack. Which was causing 'perl -Dstv' to
SEGV.
David Mitchell [Mon, 16 May 2016 12:38:21 +0000 (13:38 +0100)]
get su_init/su_pop working under 5.23.8
In 5.23.8 there are two big differences to the way perl's context system
manipulates the savestack. Firstly, pushing a scope no longer does one or
two ENTER's instead the old value of PL_savestack_ix is stored as
cx->blk_oldsaveix. This means that the boundaries of savestack frames are
now not only specified as scopestack entries, but also as blk_oldsaveix
entries.
Secondly, most values that need restoring are saved in new fields in the
CX structure rather than being pushed on the savestack; this means that it
is quite likely that two nested scopes can share the same savestack index.
This commit gets all the test scripts working that mainly test the
savestack manipulation code (su_init and su_pop).
It does this by:
*) allowing the offset by which a savestack frame boundary is adjusted to
be variable (rather than always SU_SAVE_DESTRUCTOR_SIZE), and by turning
the origin array into an array of structs, one field of which is the
offset for that depth. This allows multiple empty savestack frames
to all trigger, by ensuring that each adjusted boundary is higher than the
previous.
*) padding the savestack using SAVEt_ALLOC, which allows a variable-sized
chunk of savestack to be reserved, with minimal overhead during scope exit.
In addition,
*) the various SU_SAVE_AELEM_SIZE type macros have been rationalised and
better commented;
*) debugging output for su_init and su_pop has been improved
*) the names of context types (for debugging) have been updated for 5.23.8
and some errors fixes for older perl versions
Vincent Pit [Mon, 3 Aug 2015 13:42:36 +0000 (10:42 -0300)]
Revamp the different su_ud_* subtypes
For reap(), su_call() now only gets the SV cb and not the whole su_ud_reap
structure. This lets us free the ud in su_pop(), and likewise for
su_localize(). As for the uid feature, it gets its own su_ud_uid structure
instead of hijacking su_ud_reap, so that su_uid_bump() is no longer needed.
Vincent Pit [Fri, 24 Jul 2015 20:20:18 +0000 (17:20 -0300)]
Refactor the su_ud_common structure
The handler member is replaced by a small integer index into a static array.
The pad member is shrank so that it can be packed together with the type.
In the remaining space, we fit a private member that can be used to remove
the type member of su_ud_localize.
Vincent Pit [Fri, 24 Jul 2015 19:22:21 +0000 (16:22 -0300)]
Greatly simplify the depth computation in su_init()
In order to count how many scopes we will have to pop, it is enough to take
the difference between the current scope (PL_scopestack_ix) and the one
just below the target context (cxstack[cxix].blk_oldscopesp).
Vincent Pit [Fri, 27 Mar 2015 18:47:42 +0000 (15:47 -0300)]
Preserve PL_scopestack[cx->blk_oldscopesp - 1] in su_pop()
Starting from perl 5.19.4 commit 2537512, pp_leavesub does a second
leave_scope(PL_scopestack[cx->blk_oldscopesp - 1]) just after the usual
LEAVE call. However, this index in the scope stack may be overwritten
by our own "flush" leave_scope() call in su_pop(). More precisely, this
seems to happen in sv_clear() (called from sv_free2() called from
sv_unref_flags() called from sv_force_normal_flags() called from
leave_scope()) and only when the debugger is enabled.
Vincent Pit [Tue, 24 Mar 2015 19:54:30 +0000 (16:54 -0300)]
Update the ActivePerl/gcc-3.4 hack for EUMM 7.04
Starting from this version, PERL_ARCHIVE is quoted so we can no longer set
it to the empty string. Instead, we remove all occurrences of PERL_ARCHIVE
in the linking step section of the Makefile, which is OK since we specify
the perl DLL in other variables. This new technique is still valid for
older versions of EUMM.