Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC/WIP replace Perl stack with self allocating/expanding (C-style) stack on Win32 #13860

Open
p5pRT opened this issue May 20, 2014 · 14 comments
Labels
bulk88-query Closable? We might be able to close this ticket, but we need to check with the reporter distro-mswin32 type-core

Comments

@p5pRT
Copy link

p5pRT commented May 20, 2014

Migrated from rt.perl.org#121923 (status was 'open')

Searchable as RT121923$

@p5pRT
Copy link
Author

p5pRT commented May 20, 2014

From @bulk88

Created by @bulk88

I decided to try something novel. Replacing the Perl stack, which is a
very-often-bounds-checked malloc block, with the Win32 C stack (its not
the interp's OS thread's stack, but a thread stack without any thread).
There are around 160 calls to Perl_stack_grow, and often in hot opcodes
like pp_undef, pp_shift, pp_padsv, pp_padrange, and pp_aelemfast. Plus
we now have fancy microchips called MMUs and support for them in AT&T
SVR4. My proposal, replace the Perl stack (and maybe more stacks like
mortal stack and save stack if this works) with a self
allocating/expanding memory block, no more runtime bounds
checks+function call branches. EXTEND macro is a noop. The bounds check
is a SEGV. In POSIX land, I think this scheme would be a SIGSEGV handler
that calls mprotect to turn reserved address space into R/W memory.
Reserved address space is free. So I hacked up a POC which is attached.
And most test files pass (the others crash). So far the only 2 remaining
crash/panics problems to resolve is

-address space exhaustion on 32 bits, op/threads.t trys to launch 100
threads simultaniously, and Module​::CoreList causes huge C stack
recursion in what I guess is deeply nested tied hashes, and each
recursion of magic creates a new perl stack
-pp_split puts a AvREAL AV * into PL_curstack/PL_stack_sp for unknown to
me reason, then XPUSHs (EXTEND is a noop) onto faux-stack causing heap
corruption

There are some API design problems of how get the code integrated in a
sane way into blead.

We have SvLEN == 0 for foreign PV buffers. But what is the equivalent
for AVs?

Should PERL_FLEXIBLE_EXCEPTIONS come back since I'm use MSC's
__try/__catch?
http​://perl5.git.perl.org/perl.git/commitdiff/766f891612bf493b0430beb068ead367d70cdef6
http​://www.nntp.perl.org/group/perl.perl5.porters/2004/07/msg93066.html

In pp_mapwhile there was code starting at a very high address in the
Perl stack and wrote backwards towards lower addresses. This
broke/crashed since "guard pages" must be sequentially accesses, Win32
alloca/_chkstk (see
http​://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libgcc/config/i386/cygwin.S#l53
)/C99 non-const length array declarations have to call alloca/_chkstk to
touch each page in sequence every 4096 bytes to allocate the block and
move the guard/trap page down. IDK if this is necessary since no perl
macros write backwards/lowering addresses to the perl stack and the
couple rare times its found (like in pp_mapwhile) can be fixed by hand.
The other choice, I dont like, is for the EXTEND macro to be

# define EXTEND(p,n) (void)(UNLIKELY( (4096/sizeof(SV*)) <
(SSize_t)(n)) && \
  (sp = stack_grow(sp,p, (SSize_t) (n))))

which will constant fold away by C compiler for all const "n"s but won't
optimize away for non-const "n"s.

Currently I set the maximum VM size of Perl stack to 32 MB, which is

( 62000000[maximum # of SVs I could push() into a @​array in PP before
OOM]
  /8[reasonable largest list processing with enough src array, dest
array, and perl stack space to process the data set]
)*4[bytes per SV*]

For comparison, the Win32 C stack's default (and all Win32 Perls ever)
maximum size is fixed at 1MB. After 1 MB it stops self-allocating and
just crashes. There is a Win32 C compiler option to set it as high as
you want but I know Perl and I dont think any other apps ever touch the
setting.

How Windows/ReactOS self-allocates a thread's C stack
http​://doxygen.reactos.org/d5/d43/pagfault_8c_source.html#l00029 .

The rest of this the result of a "nmake test" on self allocating stack
perl and my notes on each test failure. If there is no note above the
test name, it means I didn't investigate the failure.

---------------------------------------------------------------
x2p/s2p.t ......................................................... ok

Test Summary Report
-------------------

\|/Heap corruption, pp_split swaps Perl stack (PL_stack_sp) with random AV
op/push.t (Wstat​:
1280 Tes
ts​: 60 Failed​: 0)
  Non-zero exit status​: 5

\|/pp_split+Error #6​: UNADDRESSABLE ACCESS​: writing
0x1147cb28-0x1147cb2c 4 byte(s)
# 0 perl520.dll!Perl_av_clear [c​:\perl519\src\av.c​:481]
# 1 perl520.dll!Perl_pp_split [c​:\perl519\src\pp.c​:5473]
# 2 perl520.dll!Perl_runops_debug [c​:\perl519\src\dump.c​:2459]
# 3 perl520.dll!S_run_body [c​:\perl519\src\win32\perl.c​:2459]
# 4 perl520.dll!perl_run [c​:\perl519\src\win32\perl.c​:2375]
# 5 perl520.dll!RunPerl [c​:\perl519\src\win32\perllib.c​:258]
# 6 main [c​:\perl519\src\win32\perlmain.c​:23]
op/split.t (Wstat​:
1280 Tes
ts​: 0 Failed​: 0)
  Non-zero exit status​: 5
  Parse errors​: No plan found in TAP output

\|/ creates 100 threads in 1 process, address space exhaustion
op/threads.t (Wstat​:
256 Test
s​: 9 Failed​: 0)
  Non-zero exit status​: 1
  Parse errors​: Bad plan. You planned 27 tests but ran 9.

\|/Heap corruption, pp_split swaps Perl stack (PL_stack_sp) with random AV
../cpan/Text-Tabs/t/sep.t (Wstat​:
1280 Tes
ts​: 25 Failed​: 0)
  Non-zero exit status​: 5
../cpan/Text-Tabs/t/sep2.t (Wstat​:
1280 Tes
ts​: 25 Failed​: 0)
  Non-zero exit status​: 5
../cpan/Text-Tabs/t/tabs.t (Wstat​:
2304 Tes
ts​: 11 Failed​: 0)
  Non-zero exit status​: 9
../cpan/Text-Tabs/t/wrap.t (Wstat​:
1280 Tes
ts​: 30 Failed​: 0)
  Non-zero exit status​: 5

\|/Address space exhaustion at
http​://perl5.git.perl.org/perl.git/blob/90b0b922bfc0b803c3769f65fbf086e6eab214fd​:/dist/Module-CoreList/lib/Module/CoreList/TieHashDelta.pm#l35
  ntdll.dll!_DbgBreakPoint@​0()
  perl520.dll!Perl_new_stackinfo(interpreter * my_perl=0x003641e4,
long stitems=32, long cxitems=41) Line 78 C
  perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4,
sv * sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c,
unsigned long flags=0, unsigned long argc=1, ...) Line 1781 + 0x76 C
  perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv
* sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c,
unsigned long flags=0, int n=1, sv * val=0x00000000) Line 1841 + 0x25 C
  perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv *
sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c) Line
1852 + 0x1b C
  perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4,
sv * sv=0x08acfa24, const magic * mg=0x08ae75e4) Line 1960 + 0x57 C
  perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv *
hv=0x08bf0b24, sv * keysv=0x08acfa04, const char * key=0x089ff4b4,
unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000,
unsigned long hash=0) Line 501 + 0x20 C
  perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4) Line
4725 + 0x1d C
  perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)
Line 2459 + 0xd C
  perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv *
sv=0x028fe44c, volatile long flags=4098) Line 2759 + 0x36 C
  perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4,
sv * sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c,
unsigned long flags=0, unsigned long argc=0, ...) Line 1806 + 0x12 C
  perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv
* sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c,
unsigned long flags=0, int n=1, sv * val=0x00000000) Line 1841 + 0x25 C
  perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv *
sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c) Line
1852 + 0x1b C
  perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4,
sv * sv=0x08acfac4, const magic * mg=0x08ae7654) Line 1960 + 0x57 C
  perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv *
hv=0x08bf3294, sv * keysv=0x08acfaa4, const char * key=0x089ff584,
unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000,
unsigned long hash=0) Line 501 + 0x20 C
  perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4) Line
4725 + 0x1d C
  perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)
Line 2459 + 0xd C
  perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv *
sv=0x028fe44c, volatile long flags=4098) Line 2759 + 0x36 C
******cut see attachment for entire callstack*****
../dist/Module-CoreList/t/corelist.t (Wstat​:
256 Test
s​: 13 Failed​: 0)
  Non-zero exit status​: 1
  Parse errors​: Bad plan. You planned 25 tests but ran 13.

\|/Same as above, address space exhaustion
../dist/Module-CoreList/t/deprecated.t (Wstat​:
256 Test
s​: 3 Failed​: 0)
  Non-zero exit status​: 1
  Parse errors​: Bad plan. You planned 9 tests but ran 3.
../dist/Module-CoreList/t/is_core.t (Wstat​:
256 Test
s​: 2 Failed​: 0)
  Non-zero exit status​: 1
  Parse errors​: Bad plan. You planned 34 tests but ran 2.
../dist/Module-CoreList/t/utils.t (Wstat​:
256 Test
s​: 2 Failed​: 0)
  Non-zero exit status​: 1
  Parse errors​: Bad plan. You planned 9 tests but ran 2.
\|/Heap corruption, pp_split swaps Perl stack (PL_stack_sp) with random AV
../lib/Tie/Array/stdpush.t (Wstat​:
1280 Tes
ts​: 60 Failed​: 0)
  Non-zero exit status​: 5
Files=2409, Tests=691333, 3367 wallclock secs (146.34 usr + 4.20 sys =
150.55 C
PU)
Result​: FAIL
NMAKE : fatal error U1077​: '..\perl.exe' : return code '0x6'
Stop.

C​:\perl519\src\win32>
-------------------------------------------------------------------

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.20.0:

Configured by Owner at Sat May 17 23:49:31 2014.

Summary of my perl5 (revision 5 version 20 subversion 0) configuration:
  Local Commit: 5b1fb5914dd2ffb35ae3286bcf8e8ee236940710
  Ancestor: e023b52d29900981e0c68349b3ec306d85c0716d
  Platform:
    osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cl', ccflags ='-nologo -GF -W3 -O1 -MD -Zi -DNDEBUG -G7 -GL 
-DWIN32 -D_CONSOLE -DNO_STRICT  -DPERL_TEXTMODE_SCRIPTS 
-DPERL_HASH_FUNC_ONE_AT_A_TIME -DPERL_IMPLICIT_CONTEXT 
-DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T',
    optimize='-O1 -MD -Zi -DNDEBUG -G7 -GL',
    cppflags='-DWIN32'
    ccversion='13.10.6030', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', 
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf 
-ltcg  -libpath:"c:\perl519\lib\CORE"  -machine:x86'
    libpth="C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\lib"
    libs=oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib  
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib  
netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  version.lib 
odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib
    perllibs=oldnames.lib kernel32.lib user32.lib gdi32.lib 
winspool.lib  comdlg32.lib advapi32.lib shell32.lib ole32.lib 
oleaut32.lib  netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib  
version.lib odbc32.lib odbccp32.lib comctl32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl520.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug 
-opt:ref,icf -ltcg  -libpath:"c:\perl519\lib\CORE"  -machine:x86'

Locally applied patches:
    RC1
    602f5d5ad824f3fd87b13b2613c3ff8ea5321bf8
    7e81d5c4f446d69f52760d5f05e193bbed8cd3db
    5b1fb5914dd2ffb35ae3286bcf8e8ee236940710


@INC for perl 5.20.0:
    C:/perl519/site/lib
    C:/perl519/lib
    .


Environment for perl 5.20.0:
    HOME (unset)
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=C:\perl519\bin;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\IDE;C:\Program Files\Microsoft Visual Studio .NET 
2003\VC7\BIN;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\Tools;C:\Program Files\Microsoft Visual Studio .NET 
2003\Common7\Tools\bin\prerelease;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\wbem;
    PERL_BADLANG (unset)
    SHELL (unset)


@p5pRT
Copy link
Author

p5pRT commented May 20, 2014

From @bulk88

commit fc3093b45eb9ff0790ca25118825401fb7e1c7e4
Author​: Daniel Dragan <bulk88@​hotmail.com>
Date​: Mon May 19 23​:07​:26 2014 -0400

  WIP replace Perl stack with C style stack on Win32

Inline Patch
commit fc3093b45eb9ff0790ca25118825401fb7e1c7e4
Author: Daniel Dragan <bulk88@hotmail.com>
Date: Mon May 19 23:07:26 2014 -0400

WIP replace Perl stack with C style stack on Win32

diff --git a/dump.c b/dump.c
index 354cd57..ddbf65d 100644
--- a/dump.c
+++ b/dump.c
@@ -2385,19 +2385,50 @@ Perl_sv_dump(pTHX_ SV *sv)
PERL_ARGS_ASSERT_SV_DUMP;

if (SvROK(sv))
do_sv_dump(0, Perl_debug_log, sv, 0, 4, 0, 0);
else
do_sv_dump(0, Perl_debug_log, sv, 0, 0, 0, 0);
}

+
+static
+DWORD
+S_fix_stack(LPEXCEPTION_POINTERS exceptions) {
+ dTHX;
+ MEMORY_BASIC_INFORMATION mbi;
+ DWORD_PTR newalloc;
+ //this is inefficient, these things should be stored somewhere in interp struct
+ if(VirtualQuery(PL_stack_base,&mbi,sizeof(mbi)) != sizeof(mbi)){
+ DebugBreak();
+ fprintf(stderr, "VQ failed %u\n", GetLastError());
+ exit(1);
+ }
+ newalloc = (DWORD_PTR)mbi.AllocationBase+(DWORD_PTR)mbi.RegionSize;
+ if(!VirtualAlloc(newalloc,
+ 4096,
+ MEM_COMMIT,
+ PAGE_READWRITE|PAGE_GUARD
+ )) {
+ DebugBreak();
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+
+
int
Perl_runops_debug(pTHX)
{
+__try
+{
dVAR;
if (!PL_op) {
Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING), "NULL OP IN RUN");
return 0;
}

DEBUG_l(Perl_deb(aTHX_ "Entering new RUNOPS level\n"));
do {
@@ -2425,16 +2456,21 @@ Perl_runops_debug(pTHX)
}

OP_ENTRY_PROBE(OP_NAME(PL_op));
} while ((PL_op = PL_op->op_ppaddr(aTHX)));
DEBUG_l(Perl_deb(aTHX_ "leaving RUNOPS level\n"));
PERL_ASYNC_CHECK();

TAINT_NOT;
+}
+//needs bounds checks to make sure the STATUS_GUARD_PAGE_VIOLATION is for Perl stack and not some other c lib doing the same thing
+__except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION ? S_fix_stack(GetExceptionInformation()) : EXCEPTION_CONTINUE_SEARCH) {
+ NOOP;
+}
return 0;
}

I32
Perl_debop(pTHX_ const OP *o)
{
dVAR;

diff --git a/perl.h b/perl.h
index 6da39f3..42ad440 100644
--- a/perl.h
+++ b/perl.h
@@ -197,16 +197,17 @@
#define _CPERLarg
#define PERL_OBJECT_THIS
#define _PERL_OBJECT_THIS
#define PERL_OBJECT_THIS_
#define CALL_FPTR(fptr) (*fptr)
#define MEMBER_TO_FPTR(name) name
#endif /* !PERL_CORE */

+//put call to func that has __try/__catch, then calls PL_runops here?
#define CALLRUNOPS PL_runops

#define CALLREGCOMP(sv, flags) Perl_pregcomp(aTHX_ (sv),(flags))

#define CALLREGCOMP_ENG(prog, sv, flags) (prog)->comp(aTHX_ sv, flags)
#define CALLREGEXEC(prog,stringarg,strend,strbeg,minend,sv,data,flags) \
RX_ENGINE(prog)->exec(aTHX_ (prog),(stringarg),(strend), \
(strbeg),(minend),(sv),(data),(flags))
diff --git a/pp.h b/pp.h
index 97738c2..0d72d2f 100644
--- a/pp.h
+++ b/pp.h
@@ -275,22 +275,22 @@ Does not use C<TARG>. See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
/* Same thing, but update mark register too. */
# define MEXTEND(p,n) STMT_START { \
const int markoff = mark - PL_stack_base; \
sp = stack_grow(sp,p,(SSize_t) (n)); \
mark = PL_stack_base + markoff; \
} STMT_END
#else
# define EXTEND(p,n) (void)(UNLIKELY(PL_stack_max - p < (SSize_t)(n)) && \
- (sp = stack_grow(sp,p, (SSize_t) (n))))
+ (sp = sp))

/* Same thing, but update mark register too. */
# define MEXTEND(p,n) STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
const int markoff = mark - PL_stack_base; \
- sp = stack_grow(sp,p,(SSize_t) (n)); \
+ sp = sp; \
mark = PL_stack_base + markoff; \
} } STMT_END
#endif

#define PUSHs(s) (*++sp = (s))
#define PUSHTARG STMT_START { SvSETMAGIC(TARG); PUSHs(TARG); } STMT_END
#define PUSHp(p,l) STMT_START { sv_setpvn(TARG, (p), (l)); PUSHTARG; } STMT_END
#define PUSHn(n) STMT_START { sv_setnv(TARG, (NV)(n)); PUSHTARG; } STMT_END
diff --git a/pp_ctl.c b/pp_ctl.c
index 380a7fe..2d4f8d2 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -996,18 +996,24 @@ PP(pp_mapwhile)
if (shift < count)
shift = count; /* Avoid shifting too often --Ben Tilly */

EXTEND(SP,shift);
src = SP;
dst = (SP += shift);
PL_markstack_ptr[-1] += shift;
*PL_markstack_ptr += shift;
- while (count--)
- *dst-- = *src--;
+ //copy upwards not downwards
+ if(count) {
+ SV** dst1 = dst;
+ SV** src1 = src;
+ dst1 -= (count-1);
+ src1 -= (count-1);
+ memcpy(dst1, src1, sizeof(SV**)*count);
+ }
}
/* copy the new items down to the destination list */
dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1;
if (gimme == G_ARRAY) {
/* add returned items to the collection (making mortal copies
* if necessary), then clear the current temps stack frame
* *except* for those items. We do this splicing the items
* into the start of the tmps frame (so some items may be on
diff --git a/run.c b/run.c
index ff3bc93..f5343d1 100644
--- a/run.c
+++ b/run.c
@@ -28,28 +28,64 @@
/*
* 'Away now, Shadowfax! Run, greatheart, run as you have never run before!
* Now we are come to the lands where you were foaled, and every stone you
* know. Run now! Hope is in speed!' --Gandalf
*
* [p.600 of _The Lord of the Rings_, III/xi: "The Palantír"]
*/

+
+static
+DWORD
+S_fix_stack(LPEXCEPTION_POINTERS exceptions) {
+ dTHX;
+ MEMORY_BASIC_INFORMATION mbi;
+ DWORD_PTR newalloc;
+ //this is inefficient, these things should be stored somewhere in interp struct
+ if(VirtualQuery(PL_stack_base,&mbi,sizeof(mbi)) != sizeof(mbi)){
+ DebugBreak();
+ fprintf(stderr, "VQ failed %u\n", GetLastError());
+ exit(1);
+ }
+ newalloc = (DWORD_PTR)mbi.AllocationBase+(DWORD_PTR)mbi.RegionSize;
+ if(!VirtualAlloc(newalloc,
+ 4096,
+ MEM_COMMIT,
+ PAGE_READWRITE|PAGE_GUARD
+ )) {
+ DebugBreak();
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+
+
int
Perl_runops_standard(pTHX)
{
+__try
+{
dVAR;
OP *op = PL_op;
OP_ENTRY_PROBE(OP_NAME(op));
while ((PL_op = op = op->op_ppaddr(aTHX))) {
OP_ENTRY_PROBE(OP_NAME(op));
}
PERL_ASYNC_CHECK();

TAINT_NOT;
+}
+//needs bounds checks to make sure the STATUS_GUARD_PAGE_VIOLATION is for Perl stack and not some other c lib doing the same thing
+__except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION ? S_fix_stack(GetExceptionInformation()) : EXCEPTION_CONTINUE_SEARCH) {
+ NOOP;
+}
return 0;
}

/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
* indent-tabs-mode: nil
diff --git a/scope.c b/scope.c
index 07f24b7..b0768b9 100644
--- a/scope.c
+++ b/scope.c
@@ -48,20 +48,64 @@ Perl_stack_grow(pTHX_ SV **sp, SV **p, SSize_t n)
#define GROW(old) ((old) + 1)
#endif

PERL_SI *
Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems)
{
dVAR;
PERL_SI *si;
+ void *avarr;
+ void * avarr2;
+ void * toalloc;
Newx(si, 1, PERL_SI);
si->si_stack = newAV();
AvREAL_off(si->si_stack);
- av_extend(si->si_stack, stitems > 0 ? stitems-1 : 0);
+ //av_extend(si->si_stack, stitems > 0 ? stitems-1 : 0);
+ Safefree(AvALLOC(si->si_stack));
+ AvALLOC(si->si_stack) = NULL;
+ AvARRAY(si->si_stack) = NULL;
+ AvMAX(si->si_stack) = SSize_t_MAX/sizeof(SV*);
+ fprintf(stderr, "stack alloc NSI av=%x\n", si->si_stack);
+ avarr = VirtualAlloc(
+ NULL,
+ 33554432, //2^25 32 MB
+ MEM_RESERVE,
+ PAGE_NOACCESS
+ );
+ if(!avarr) {
+ DWORD e = GetLastError();
+ DebugBreak();
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ //4096 (page size) should be constant or runtime lookup from Win32 API, for
+ //constant research 32 and 64 bit behavior and meaning of "large pages"
+ if(! (avarr2 = VirtualAlloc(avarr,
+ 4096,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ ))) {
+ DebugBreak();
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ (DWORD_PTR)toalloc = (DWORD_PTR)avarr+(DWORD_PTR)4096;
+ if(!VirtualAlloc(toalloc,
+ 4096,
+ MEM_COMMIT,
+ PAGE_READWRITE|PAGE_GUARD
+ )) {
+ DebugBreak();
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ AvALLOC(si->si_stack) = (SV**)avarr;
+ AvARRAY(si->si_stack) = (SV**)avarr;
+
AvALLOC(si->si_stack)[0] = &PL_sv_undef;
AvFILLp(si->si_stack) = 0;
si->si_prev = 0;
si->si_next = 0;
si->si_cxmax = cxitems - 1;
si->si_cxix = -1;
si->si_type = PERLSI_UNDEF;
Newx(si->si_cxstack, cxitems, PERL_CONTEXT);
diff --git a/sv.c b/sv.c
index b43fadf..7301b24 100644
--- a/sv.c
+++ b/sv.c
@@ -6427,17 +6427,30 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
if (AvREAL(av) && AvFILLp(av) > -1) {
next_sv = AvARRAY(av)[AvFILLp(av)--];
/* save old iter_sv in top-most slot of AV,
* and pray that it doesn't get wiped in the meantime */
AvARRAY(av)[AvMAX(av)] = iter_sv;
iter_sv = sv;
goto get_next_sv; /* process this new sv */
}
- Safefree(AvALLOC(av));
+ if(!AvREAL((const AV *)av) && AvMAX((const AV *)av) == SSize_t_MAX/sizeof(SV*)) {
+ fprintf(stderr, "stack dealloc av=%x\n", av);
+ if(!VirtualFree(
+ AvALLOC(av),
+ 0,
+ MEM_RELEASE
+ )) {
+ fprintf(stderr, "VF failed %u\n", GetLastError());
+ exit(1);
+ }
+ }
+ else {
+ Safefree(AvALLOC(av));
+ }
}

break;
case SVt_PVLV:
if (LvTYPE(sv) == 'T') { /* for tie: return HE to pool */
SvREFCNT_dec(HeKEY_sv((HE*)LvTARG(sv)));
HeNEXT((HE*)LvTARG(sv)) = PL_hv_fetch_ent_mh;
PL_hv_fetch_ent_mh = (HE*)LvTARG(sv);
@@ -6771,23 +6784,28 @@ Perl_sv_free(pTHX_ SV *const sv)
{
SvREFCNT_dec(sv);
}


/* Private helper function for SvREFCNT_dec().
* Called with rc set to original SvREFCNT(sv), where rc == 0 or 1 */

+SV * watch_sv;
+
void
Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
{
dVAR;

PERL_ARGS_ASSERT_SV_FREE2;

+ if( sv == watch_sv) {
+ DebugBreak();
+ }
if (LIKELY( rc == 1 )) {
/* normal case */
SvREFCNT(sv) = 0;

#ifdef DEBUGGING
if (SvTEMP(sv)) {
Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING),
"Attempt to free temp prematurely: SV 0x%"UVxf
@@ -12675,32 +12693,74 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
break;
case SVt_PVAV:
/* avoid cloning an empty array */
if (AvARRAY((const AV *)sstr) && AvFILLp((const AV *)sstr) >= 0) {
SV **dst_ary, **src_ary;
SSize_t items = AvFILLp((const AV *)sstr) + 1;

src_ary = AvARRAY((const AV *)sstr);
- Newxz(dst_ary, AvMAX((const AV *)sstr)+1, SV*);
+ if(!AvREAL((const AV *)sstr) && AvMAX((const AV *)sstr) == SSize_t_MAX/sizeof(SV*)) {
+ MEMORY_BASIC_INFORMATION mbi;
+ void * avarr;
+ DWORD_PTR toalloc;
+ void * avarr2;
+ fprintf(stderr, "stack alloc S_sv_dup_common src av=%x dst av=%x\n", sstr, dstr);
+ if(VirtualQuery(src_ary,&mbi,sizeof(mbi)) != sizeof(mbi)){
+ DebugBreak();
+ fprintf(stderr, "VQ failed %u\n", GetLastError());
+ exit(1);
+ }
+ avarr = VirtualAlloc(
+ NULL,
+ 33554432, //2^25 32 MB
+ MEM_RESERVE,
+ PAGE_NOACCESS
+ );
+ if(!avarr) {
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ if(! (avarr2 = VirtualAlloc(avarr,
+ mbi.RegionSize,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ ))) {
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ toalloc = (DWORD_PTR) avarr + mbi.RegionSize;
+ if(!VirtualAlloc(toalloc,
+ 4096,
+ MEM_COMMIT,
+ PAGE_READWRITE|PAGE_GUARD
+ )) {
+ fprintf(stderr, "VA failed %u\n", GetLastError());
+ exit(1);
+ }
+ dst_ary = avarr;
+ } else {
+ Newxz(dst_ary, AvMAX((const AV *)sstr)+1, SV*);
+ }
ptr_table_store(PL_ptr_table, src_ary, dst_ary);
AvARRAY(MUTABLE_AV(dstr)) = dst_ary;
AvALLOC((const AV *)dstr) = dst_ary;
if (AvREAL((const AV *)sstr)) {
dst_ary = sv_dup_inc_multiple(src_ary, dst_ary, items,
param);
}
else {
while (items-- > 0)
*dst_ary++ = sv_dup(*src_ary++, param);
}
- items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr);
- while (items-- > 0) {
- *dst_ary++ = &PL_sv_undef;
- }
+ //is this really needed? This is uninit space I think
+ // items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr);
+ // while (items-- > 0) {
+ // *dst_ary++ = &PL_sv_undef;
+ // }
}
else {
AvARRAY(MUTABLE_AV(dstr)) = NULL;
AvALLOC((const AV *)dstr) = (SV**)NULL;
AvMAX( (const AV *)dstr) = -1;
AvFILLp((const AV *)dstr) = -1;
}
break;

@p5pRT
Copy link
Author

p5pRT commented May 20, 2014

From @bulk88

tied_hash_deep_c_recursion_overflow.txt

Address space exhaustion at http://perl5.git.perl.org/perl.git/blob/90b0b922bfc0b803c3769f65fbf086e6eab214fd:/dist/Module-CoreList/lib/Module/CoreList/TieHashDelta.pm#l35
     ntdll.dll!_DbgBreakPoint@0()    
     perl520.dll!Perl_new_stackinfo(interpreter * my_perl=0x003641e4, long stitems=32, long cxitems=41)  Line 78    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=1, ...)  Line 1781 + 0x76    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfa24, const magic * mg=0x08ae75e4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfa24, const magic * mg=0x08ae75e4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf0b24, sv * keysv=0x08acfa04, const char * key=0x089ff4b4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfac4, const magic * mg=0x08ae7654, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfac4, const magic * mg=0x08ae7654)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf3294, sv * keysv=0x08acfaa4, const char * key=0x089ff584, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfb64, const magic * mg=0x08ae76c4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfb64, const magic * mg=0x08ae76c4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfb64, const magic * mg=0x08ae76c4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfb64, const magic * mg=0x08ae76c4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf3734, sv * keysv=0x08acfb44, const char * key=0x089ff654, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfc04, const magic * mg=0x08ae7914, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfc04, const magic * mg=0x08ae7914, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfc04, const magic * mg=0x08ae7914, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfc04, const magic * mg=0x08ae7914)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf3974, sv * keysv=0x08acfbe4, const char * key=0x089ff724, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfca4, const magic * mg=0x08ae8b1c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfca4, const magic * mg=0x08ae8b1c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfca4, const magic * mg=0x08ae8b1c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfca4, const magic * mg=0x08ae8b1c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf3ea4, sv * keysv=0x08acfc84, const char * key=0x089ffb7c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfd44, const magic * mg=0x08ae8b8c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfd44, const magic * mg=0x08ae8b8c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfd44, const magic * mg=0x08ae8b8c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfd44, const magic * mg=0x08ae8b8c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bf6dac, sv * keysv=0x08acfd24, const char * key=0x089ffe2c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfde4, const magic * mg=0x08ae8d34, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfde4, const magic * mg=0x08ae8d34, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfde4, const magic * mg=0x08ae8d34, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfde4, const magic * mg=0x08ae8d34)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bfa654, sv * keysv=0x08acfdc4, const char * key=0x089fff6c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acfe84, const magic * mg=0x08ae8da4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acfe84, const magic * mg=0x08ae8da4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfe84, const magic * mg=0x08ae8da4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acfe84, const magic * mg=0x08ae8da4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bfc0fc, sv * keysv=0x08acfe64, const char * key=0x08a0003c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acff24, const magic * mg=0x08ae8e84, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acff24, const magic * mg=0x08ae8e84, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acff24, const magic * mg=0x08ae8e84, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acff24, const magic * mg=0x08ae8e84)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bffccc, sv * keysv=0x08acff04, const char * key=0x08a0010c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08acffc4, const magic * mg=0x08ae8e14, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08acffc4, const magic * mg=0x08ae8e14, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08acffc4, const magic * mg=0x08ae8e14, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08acffc4, const magic * mg=0x08ae8e14)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08bfff3c, sv * keysv=0x08acffa4, const char * key=0x08a001dc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0064, const magic * mg=0x08ae901c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0064, const magic * mg=0x08ae901c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0064, const magic * mg=0x08ae901c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0064, const magic * mg=0x08ae901c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c031d4, sv * keysv=0x08ad0034, const char * key=0x08a00534, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0104, const magic * mg=0x08ae9c54, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0104, const magic * mg=0x08ae9c54, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0104, const magic * mg=0x08ae9c54, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0104, const magic * mg=0x08ae9c54)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c08c84, sv * keysv=0x08ad00e4, const char * key=0x08a02d1c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad01a4, const magic * mg=0x08ae9d2c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad01a4, const magic * mg=0x08ae9d2c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad01a4, const magic * mg=0x08ae9d2c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad01a4, const magic * mg=0x08ae9d2c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c0c5b4, sv * keysv=0x08ad0184, const char * key=0x08a02e5c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0244, const magic * mg=0x08aea594, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0244, const magic * mg=0x08aea594, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0244, const magic * mg=0x08aea594, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad0244, const magic * mg=0x08aea594)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c0e72c, sv * keysv=0x08ad0224, const char * key=0x08a02f9c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5764, const magic * mg=0x08aea604, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5764, const magic * mg=0x08aea604, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5764, const magic * mg=0x08aea604, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5764, const magic * mg=0x08aea604)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c0ea0c, sv * keysv=0x08ad5744, const char * key=0x08a03a44, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5804, const magic * mg=0x08aea674, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5804, const magic * mg=0x08aea674, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5804, const magic * mg=0x08aea674, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5804, const magic * mg=0x08aea674)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c117e4, sv * keysv=0x08ad57e4, const char * key=0x08a03004, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad58a4, const magic * mg=0x08aeba7c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad58a4, const magic * mg=0x08aeba7c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad58a4, const magic * mg=0x08aeba7c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad58a4, const magic * mg=0x08aeba7c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c13bb4, sv * keysv=0x08ad5884, const char * key=0x08a04274, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5944, const magic * mg=0x08aebaec, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5944, const magic * mg=0x08aebaec, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5944, const magic * mg=0x08aebaec, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5944, const magic * mg=0x08aebaec)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c1685c, sv * keysv=0x08ad5924, const char * key=0x089ff244, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad59e4, const magic * mg=0x08aebc94, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad59e4, const magic * mg=0x08aebc94, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad59e4, const magic * mg=0x08aebc94, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad59e4, const magic * mg=0x08aebc94)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c18d8c, sv * keysv=0x08ad59c4, const char * key=0x08a069e4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5a84, const magic * mg=0x08aebdf4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5a84, const magic * mg=0x08aebdf4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5a84, const magic * mg=0x08aebdf4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5a84, const magic * mg=0x08aebdf4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c1addc, sv * keysv=0x08ad5a64, const char * key=0x08a06b9c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5b24, const magic * mg=0x08aebf54, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5b24, const magic * mg=0x08aebf54, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5b24, const magic * mg=0x08aebf54, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5b24, const magic * mg=0x08aebf54)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c1ea7c, sv * keysv=0x08ad5b04, const char * key=0x08a074ec, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5bc4, const magic * mg=0x08aec0b4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5bc4, const magic * mg=0x08aec0b4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5bc4, const magic * mg=0x08aec0b4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5bc4, const magic * mg=0x08aec0b4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2e984, sv * keysv=0x08ad5ba4, const char * key=0x08a075bc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5c64, const magic * mg=0x08aec214, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5c64, const magic * mg=0x08aec214, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5c64, const magic * mg=0x08aec214, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5c64, const magic * mg=0x08aec214)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2ea04, sv * keysv=0x08ad5c44, const char * key=0x08a07874, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5d04, const magic * mg=0x08aec3e4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5d04, const magic * mg=0x08aec3e4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5d04, const magic * mg=0x08aec3e4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5d04, const magic * mg=0x08aec3e4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2ea84, sv * keysv=0x08ad5ce4, const char * key=0x08a090d4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5da4, const magic * mg=0x08aec71c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5da4, const magic * mg=0x08aec71c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5da4, const magic * mg=0x08aec71c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5da4, const magic * mg=0x08aec71c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2eb04, sv * keysv=0x08ad5d84, const char * key=0x08a0934c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5e44, const magic * mg=0x08aec374, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5e44, const magic * mg=0x08aec374, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5e44, const magic * mg=0x08aec374, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5e44, const magic * mg=0x08aec374)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2eb84, sv * keysv=0x08ad5e24, const char * key=0x08a094e4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5ee4, const magic * mg=0x08aeeb8c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5ee4, const magic * mg=0x08aeeb8c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5ee4, const magic * mg=0x08aeeb8c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5ee4, const magic * mg=0x08aeeb8c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2ec04, sv * keysv=0x08ad5ec4, const char * key=0x08a097a4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5f84, const magic * mg=0x08aeebfc, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5f84, const magic * mg=0x08aeebfc, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5f84, const magic * mg=0x08aeebfc, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad5f84, const magic * mg=0x08aeebfc)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2ec84, sv * keysv=0x08ad5f64, const char * key=0x08a09afc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6024, const magic * mg=0x08aeecd4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6024, const magic * mg=0x08aeecd4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6024, const magic * mg=0x08aeecd4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6024, const magic * mg=0x08aeecd4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c2ed04, sv * keysv=0x08ad6004, const char * key=0x08a09bcc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad60c4, const magic * mg=0x08aeed44, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad60c4, const magic * mg=0x08aeed44, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad60c4, const magic * mg=0x08aeed44, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad60c4, const magic * mg=0x08aeed44)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34714, sv * keysv=0x08ad60a4, const char * key=0x08a09c9c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6164, const magic * mg=0x08aeee1c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6164, const magic * mg=0x08aeee1c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6164, const magic * mg=0x08aeee1c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6164, const magic * mg=0x08aeee1c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34794, sv * keysv=0x08ad6144, const char * key=0x08a09f04, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6204, const magic * mg=0x08aeee8c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6204, const magic * mg=0x08aeee8c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6204, const magic * mg=0x08aeee8c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6204, const magic * mg=0x08aeee8c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34814, sv * keysv=0x08ad61e4, const char * key=0x08a0a494, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad62a4, const magic * mg=0x08aeeefc, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad62a4, const magic * mg=0x08aeeefc, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad62a4, const magic * mg=0x08aeeefc, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad62a4, const magic * mg=0x08aeeefc)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34894, sv * keysv=0x08ad6284, const char * key=0x08a0a724, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6344, const magic * mg=0x08aeef6c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6344, const magic * mg=0x08aeef6c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6344, const magic * mg=0x08aeef6c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6344, const magic * mg=0x08aeef6c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34914, sv * keysv=0x08ad6324, const char * key=0x08a0c924, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad63e4, const magic * mg=0x08aeefdc, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad63e4, const magic * mg=0x08aeefdc, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad63e4, const magic * mg=0x08aeefdc, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad63e4, const magic * mg=0x08aeefdc)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34c14, sv * keysv=0x08ad63c4, const char * key=0x08a0ca5c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6484, const magic * mg=0x08aef414, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6484, const magic * mg=0x08aef414, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6484, const magic * mg=0x08aef414, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6484, const magic * mg=0x08aef414)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34c94, sv * keysv=0x08ad6464, const char * key=0x08a0cc3c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6524, const magic * mg=0x08aef484, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6524, const magic * mg=0x08aef484, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6524, const magic * mg=0x08aef484, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6524, const magic * mg=0x08aef484)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34d14, sv * keysv=0x08ad6504, const char * key=0x08a0cd0c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad65c4, const magic * mg=0x08aef4f4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad65c4, const magic * mg=0x08aef4f4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad65c4, const magic * mg=0x08aef4f4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad65c4, const magic * mg=0x08aef4f4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34d94, sv * keysv=0x08ad65a4, const char * key=0x08a0cddc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6664, const magic * mg=0x08aef5d4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6664, const magic * mg=0x08aef5d4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6664, const magic * mg=0x08aef5d4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ad6664, const magic * mg=0x08aef5d4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34e14, sv * keysv=0x08ad6644, const char * key=0x08a0ceac, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adcc34, const magic * mg=0x08aefe34, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adcc34, const magic * mg=0x08aefe34, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcc34, const magic * mg=0x08aefe34, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcc34, const magic * mg=0x08aefe34)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34e94, sv * keysv=0x08ad66e4, const char * key=0x08a0cf7c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adccd4, const magic * mg=0x08aeff0c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adccd4, const magic * mg=0x08aeff0c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adccd4, const magic * mg=0x08aeff0c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adccd4, const magic * mg=0x08aeff0c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34f14, sv * keysv=0x08adccb4, const char * key=0x08a0d2ac, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adcd74, const magic * mg=0x08aef564, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adcd74, const magic * mg=0x08aef564, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcd74, const magic * mg=0x08aef564, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcd74, const magic * mg=0x08aef564)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c34f94, sv * keysv=0x08adcd54, const char * key=0x08a0cfe4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3714, const magic * mg=0x08af082c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3714, const magic * mg=0x08af082c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3714, const magic * mg=0x08af082c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3714, const magic * mg=0x08af082c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35014, sv * keysv=0x08ae3634, const char * key=0x08a0d7fc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adce04, const magic * mg=0x08af089c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adce04, const magic * mg=0x08af089c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adce04, const magic * mg=0x08af089c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adce04, const magic * mg=0x08af089c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35094, sv * keysv=0x08adcde4, const char * key=0x08a0d93c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3824, const magic * mg=0x08af2164, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3824, const magic * mg=0x08af2164, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3824, const magic * mg=0x08af2164, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3824, const magic * mg=0x08af2164)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35114, sv * keysv=0x08ae3804, const char * key=0x08a0da0c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adcef4, const magic * mg=0x08af21d4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adcef4, const magic * mg=0x08af21d4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcef4, const magic * mg=0x08af21d4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcef4, const magic * mg=0x08af21d4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35194, sv * keysv=0x08ae3914, const char * key=0x08a0ed7c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08adcf94, const magic * mg=0x08af22ac, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08adcf94, const magic * mg=0x08af22ac, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcf94, const magic * mg=0x08af22ac, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08adcf94, const magic * mg=0x08af22ac)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35214, sv * keysv=0x08adcf74, const char * key=0x08a10f54, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add034, const magic * mg=0x08af231c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add034, const magic * mg=0x08af231c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add034, const magic * mg=0x08af231c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add034, const magic * mg=0x08af231c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35414, sv * keysv=0x08add014, const char * key=0x08a112ac, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add0d4, const magic * mg=0x08af23f4, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add0d4, const magic * mg=0x08af23f4, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add0d4, const magic * mg=0x08af23f4, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add0d4, const magic * mg=0x08af23f4)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35494, sv * keysv=0x08add0b4, const char * key=0x08a115b4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add104, const magic * mg=0x08af2464, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add104, const magic * mg=0x08af2464, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add104, const magic * mg=0x08af2464, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add104, const magic * mg=0x08af2464)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35514, sv * keysv=0x08add0e4, const char * key=0x08a0f0b4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add134, const magic * mg=0x08a1c6ec, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add134, const magic * mg=0x08a1c6ec, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add134, const magic * mg=0x08a1c6ec, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add134, const magic * mg=0x08a1c6ec)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35594, sv * keysv=0x08add114, const char * key=0x08a1dfdc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add164, const magic * mg=0x02976074, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add164, const magic * mg=0x02976074, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add164, const magic * mg=0x02976074, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add164, const magic * mg=0x02976074)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35614, sv * keysv=0x08add144, const char * key=0x08a1e244, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add194, const magic * mg=0x029e1b64, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add194, const magic * mg=0x029e1b64, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add194, const magic * mg=0x029e1b64, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add194, const magic * mg=0x029e1b64)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c35694, sv * keysv=0x08add174, const char * key=0x08a1791c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add1c4, const magic * mg=0x0299ee24, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add1c4, const magic * mg=0x0299ee24, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add1c4, const magic * mg=0x0299ee24, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add1c4, const magic * mg=0x0299ee24)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c39134, sv * keysv=0x08add1a4, const char * key=0x08a1db34, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add1f4, const magic * mg=0x08a5fa14, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add1f4, const magic * mg=0x08a5fa14, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add1f4, const magic * mg=0x08a5fa14, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add1f4, const magic * mg=0x08a5fa14)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c391b4, sv * keysv=0x08add1d4, const char * key=0x08a14234, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add224, const magic * mg=0x08a504fc, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add224, const magic * mg=0x08a504fc, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add224, const magic * mg=0x08a504fc, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add224, const magic * mg=0x08a504fc)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c39234, sv * keysv=0x08add204, const char * key=0x08a15034, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add254, const magic * mg=0x08b0f784, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add254, const magic * mg=0x08b0f784, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add254, const magic * mg=0x08b0f784, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add254, const magic * mg=0x08b0f784)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c392b4, sv * keysv=0x08add234, const char * key=0x08a168bc, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add274, const magic * mg=0x08a504bc, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add274, const magic * mg=0x08a504bc, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add274, const magic * mg=0x08a504bc, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add274, const magic * mg=0x08a504bc)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c39334, sv * keysv=0x08add264, const char * key=0x08a1154c, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08add2a4, const magic * mg=0x08a7827c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08add2a4, const magic * mg=0x08a7827c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08add2a4, const magic * mg=0x08a7827c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08add2a4, const magic * mg=0x08a7827c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c39534, sv * keysv=0x08add284, const char * key=0x08a07aa4, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!Perl_call_sv(interpreter * my_perl=0x003641e4, sv * sv=0x028fe44c, volatile long flags=4098)  Line 2759 + 0x36    C
     perl520.dll!Perl_magic_methcall(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3954, const magic * mg=0x08b0fc0c, sv * meth=0x028fe44c, unsigned long flags=0, unsigned long argc=0, ...)  Line 1806 + 0x12    C
     perl520.dll!S_magic_methcall1(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3954, const magic * mg=0x08b0fc0c, sv * meth=0x028fe44c, unsigned long flags=0, int n=1, sv * val=0x00000000)  Line 1841 + 0x25    C
     perl520.dll!S_magic_methpack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3954, const magic * mg=0x08b0fc0c, sv * meth=0x028fe44c)  Line 1852 + 0x1b    C
     perl520.dll!Perl_magic_existspack(interpreter * my_perl=0x003641e4, sv * sv=0x08ae3954, const magic * mg=0x08b0fc0c)  Line 1960 + 0x57    C
     perl520.dll!Perl_hv_common(interpreter * my_perl=0x003641e4, hv * hv=0x08c395b4, sv * keysv=0x08ae3934, const char * key=0x08a2be64, unsigned int klen=8, int flags=0, int action=8, sv * val=0x00000000, unsigned long hash=0)  Line 501 + 0x20    C
     perl520.dll!Perl_pp_exists(interpreter * my_perl=0x003641e4)  Line 4725 + 0x1d    C
     perl520.dll!Perl_runops_debug(interpreter * my_perl=0x003641e4)  Line 2459 + 0xd    C
     perl520.dll!S_run_body(interpreter * my_perl=0x003641e4, long oldscope=1)  Line 2459 + 0xd    C
     perl520.dll!perl_run(interpreter * my_perl=0x003641e4)  Line 2378    C
     perl520.dll!RunPerl(int argc=3, char * * argv=0x00362cf0, char * * env=0x00365820)  Line 258 + 0x9    C++
     perl.exe!main(int argc=3, char * * argv=0x00362cf0, char * * env=0x00363280)  Line 23 + 0x12    C
     perl.exe!mainCRTStartup()  Line 398 + 0xe    C
     kernel32.dll!_BaseProcessStart@4()  + 0x23    

@p5pRT
Copy link
Author

p5pRT commented May 21, 2014

From @tonycoz

On Mon May 19 21​:52​:25 2014, bulk88 wrote​:

I decided to try something novel. Replacing the Perl stack, which is a
very-often-bounds-checked malloc block, with the Win32 C stack (its
not
the interp's OS thread's stack, but a thread stack without any
thread).
There are around 160 calls to Perl_stack_grow, and often in hot
opcodes
like pp_undef, pp_shift, pp_padsv, pp_padrange, and pp_aelemfast. Plus
we now have fancy microchips called MMUs and support for them in AT&T
SVR4. My proposal, replace the Perl stack (and maybe more stacks like
mortal stack and save stack if this works) with a self
allocating/expanding memory block, no more runtime bounds
checks+function call branches. EXTEND macro is a noop. The bounds
check
is a SEGV. In POSIX land, I think this scheme would be a SIGSEGV
handler
that calls mprotect to turn reserved address space into R/W memory.
Reserved address space is free. So I hacked up a POC which is
attached.
And most test files pass (the others crash). So far the only 2
remaining
crash/panics problems to resolve is

-address space exhaustion on 32 bits, op/threads.t trys to launch 100
threads simultaniously, and Module​::CoreList causes huge C stack
recursion in what I guess is deeply nested tied hashes, and each
recursion of magic creates a new perl stack
-pp_split puts a AvREAL AV * into PL_curstack/PL_stack_sp for unknown
to
me reason, then XPUSHs (EXTEND is a noop) onto faux-stack causing heap
corruption

Wouldn't it be simpler to just use an anonymous file mapping?

Without SEC_COMMIT you're just allocating address space, similar to using MAP_NORESERVE for anonymous mmap() on Linux (and Solaris.)

Unfortunately MAP_NORESERVE isn't standardized and doesn't seem to be available on the BSDs (anonymous mapping also isn't standardized, but appears to be more commonly implemented.)

The main problem I see is one you've touched on - address space exhaustion on 32-bit platforms.

The current mechanism allows for a large stack in a single thread, many threads with small stacks, a small stack with large SVs and other variations I'm not going to enumerate.

Allocating large sections of address space would limit the way that a perl prcoess could use[1] memory too much.

Tony

[1] over-use, as many would say :)

@p5pRT
Copy link
Author

p5pRT commented May 21, 2014

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented May 29, 2014

From @bulk88

I already wrote a response and posted it a week ago, but somehow it never made it, so I am retyping it from memory. (logged out?/cookies)

On Tue May 20 22​:30​:53 2014, tonyc wrote​:

Wouldn't it be simpler to just use an anonymous file mapping?

No. Using a file mapping means having to keep track of a kernel file handle inaddition to the pointer to the memory block. Anon file mappings are for inter-process shared memory. Perl has no reason to share the perl stack with another process. Also file mappings are used for sliding memory "windows" into a larger file (for example, for files too large to memory map entirely). Again that has no use for perl. Both VirtualAlloc and null/invalid file handle CreateFileMapping memory is subject to standard ejection from physical memory to paging file rules. CreateFileMapping is just alot more complicated for no benefit.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Jun 3, 2014

From @bulk88

I thought about the self allocating concept on *nix. Is an sbrk and/or mmap region of pages, when initially allocated and NULL filled, COWed to a single inter-process shared page of NULLs until it is written to, making the page "dirty" and then being added to the non-shared private pool of the process?

If this is true, the idea on *nix, this idea in this commit, can just allocates a large region of pages, and not "reserve" address space (which later would require a mprotect call in the segv handler to allocate), but keeps the pages allocated from the moment of address space allocation creation? Thus removing the need for a segv handler. Of course this is highly specific to the design of the *nix kernel I think. Since if it can't COW/map together new NULL filled pages until they are first written to, this idea will burn physical memory like crazy.

After some more work on the concept, I've given up on trying to extract from pp_split, the swap the perl stack with a GV AV or pad AV, then PUSHs onto the AvREAL (I think) AV trick from Perl 3.0 from http​://perl5.git.perl.org/perl.git/commitdiff/a687059cbaf2c6fdccb5e0fae2aee80ec15625a8 . Here is a diff of where this swap perl stack with a random AV code came from. If you look in the 3.0 patch, the only part of the code that is recognizable to blead today is the comment "/* temporarily switch stacks */". I'm guessing this trick was a memory optimization.

--- C:\perl521\src\do_splitold.txt
+++ C:\perl521\src\do_splitnew.txt
@@ -1,94 +1,189 @@
int
-do_split(spat,retary,sarg,ptrmaxsarg,sargoff,cushion)
+do_split(str,spat,limit,gimme,arglast)
+STR *str;
register SPAT *spat;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
+register int limit;
+int gimme;
+int *arglast;
{
- register char *s = str_get(sarg[1]);
- char *strend = s + sarg[1]->str_cur;
+ register ARRAY *ary = stack;
+ STR **st = ary->ary_array;
+ register int sp = arglast[0] + 1;
+ register char *s = str_get(st[sp]);
+ char *strend = s + st[sp--]->str_cur;
register STR *dstr;
register char *m;
- register ARRAY *ary;
- static ARRAY *myarray = Null(ARRAY*);
int iters = 0;
int i;
+ char *orig;
+ int origlimit = limit;
+ int realarray = 0;

if (!spat || !s)
fatal("panic: do_split");
else if (spat->spat_runtime) {
- m = str_get(eval(spat->spat_runtime,Null(STR***),-1));
- if (!*m || (*m == ' ' && !m[1])) {
- m = "\\s+";
+ nointrp = "|)";
+ sp = eval(spat->spat_runtime,G_SCALAR,sp);
+ st = stack->ary_array;
+ m = str_get(dstr = st[sp--]);
+ nointrp = "";
+ if (!dstr->str_cur || (*m == ' ' && dstr->str_cur == 1)) {
+ str_set(dstr,"\\s+");
+ m = dstr->str_ptr;
spat->spat_flags |= SPAT_SKIPWHITE;
}
- if (spat->spat_runtime->arg_type == O_ITEM &&
- spat->spat_runtime[1].arg_type == A_SINGLE) {
+ if (spat->spat_regexp)
+ regfree(spat->spat_regexp);
+ spat->spat_regexp = regcomp(m,m+dstr->str_cur,
+ spat->spat_flags & SPAT_FOLD,1);
+ if (spat->spat_flags & SPAT_KEEP ||
+ (spat->spat_runtime->arg_type == O_ITEM &&
+ (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
arg_free(spat->spat_runtime); /* it won't change, so */
spat->spat_runtime = Nullarg; /* no point compiling again */
}
- spat->spat_regexp = regcomp(m,spat->spat_flags & SPAT_FOLD,1);
}
#ifdef DEBUGGING
if (debug & 8) {
deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
}
#endif
- if (retary)
- ary = myarray;
+ ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
+ if (ary && ((ary->ary_flags & ARF_REAL) || gimme != G_ARRAY)) {
+ ary->ary_flags |= ARF_REAL;
+ realarray = 1;
+ ary->ary_fill = -1;
+ sp = -1; /* temporarily switch stacks */
+ }
else
- ary = spat->spat_repl[1].arg_ptr.arg_stab->stab_array;
- if (!ary)
- myarray = ary = anew(Nullstab);
- ary->ary_fill = -1;
+ ary = stack;
+ orig = s;
if (spat->spat_flags & SPAT_SKIPWHITE) {
while (isspace(*s))
s++;
}
+ if (!limit)
+ limit = 10001;
if (spat->spat_short) {
i = spat->spat_short->str_cur;
- while (*s && (m = fbminstr(s, strend, spat->spat_short))) {
- dstr = str_new(m-s);
- str_nset(dstr,s,m-s);
- astore(ary, iters++, dstr);
- if (iters > 10000)
- fatal("Substitution loop");
- s = m + i;
+ if (i == 1) {
+ i = *spat->spat_short->str_ptr;
+ while (--limit) {
+ for (m = s; m < strend && *m != i; m++) ;
+ if (m >= strend)
+ break;
+ if (realarray)
+ dstr = Str_new(30,m-s);
+ else
+ dstr = str_static(&str_undef);
+ str_nset(dstr,s,m-s);
+ (void)astore(ary, ++sp, dstr);
+ s = m + 1;
+ }
+ }
+ else {
+#ifndef lint
+ while (s < strend && --limit &&
+ (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
+ spat->spat_short)) )
+#endif
+ {
+ if (realarray)
+ dstr = Str_new(31,m-s);
+ else
+ dstr = str_static(&str_undef);
+ str_nset(dstr,s,m-s);
+ (void)astore(ary, ++sp, dstr);
+ s = m + i;
+ }
}
}
else {
- while (*s && regexec(spat->spat_regexp, s, strend, (iters == 0), 1,
- Nullstr)) {
+ while (s < strend && --limit &&
+ regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
+ if (spat->spat_regexp->subbase
+ && spat->spat_regexp->subbase != orig) {
+ m = s;
+ s = orig;
+ orig = spat->spat_regexp->subbase;
+ s = orig + (m - s);
+ strend = s + (strend - m);
+ }
m = spat->spat_regexp->startp[0];
- if (spat->spat_regexp->subbase)
- s = spat->spat_regexp->subbase;
- dstr = str_new(m-s);
+ if (realarray)
+ dstr = Str_new(32,m-s);
+ else
+ dstr = str_static(&str_undef);
str_nset(dstr,s,m-s);
- astore(ary, iters++, dstr);
- if (iters > 10000)
- fatal("Substitution loop");
+ (void)astore(ary, ++sp, dstr);
+ if (spat->spat_regexp->nparens) {
+ for (i = 1; i <= spat->spat_regexp->nparens; i++) {
+ s = spat->spat_regexp->startp[i];
+ m = spat->spat_regexp->endp[i];
+ if (realarray)
+ dstr = Str_new(33,m-s);
+ else
+ dstr = str_static(&str_undef);
+ str_nset(dstr,s,m-s);
+ (void)astore(ary, ++sp, dstr);
+ }
+ }
s = spat->spat_regexp->endp[0];
}
}
- if (*s) { /* ignore field after final "whitespace" */
- dstr = str_new(0); /* if they interpolate, it's null anyway */
- str_set(dstr,s);
- astore(ary, iters++, dstr);
+ if (realarray)
+ iters = sp + 1;
+ else
+ iters = sp - arglast[0];
+ if (iters > 9999)
+ fatal("Split loop");
+ if (s < strend || origlimit) { /* keep field after final delim? */
+ if (realarray)
+ dstr = Str_new(34,strend-s);
+ else
+ dstr = str_static(&str_undef);
+ str_nset(dstr,s,strend-s);
+ (void)astore(ary, ++sp, dstr);
+ iters++;
}
else {
- while (iters > 0 && !*str_get(afetch(ary,iters-1)))
- iters--;
+#ifndef I286
+ while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
+ iters--,sp--;
+#else
+ char *zaps;
+ int zapb;
+
+ if (iters > 0) {
+ zaps = str_get(afetch(ary,sp,FALSE));
+ zapb = (int) *zaps;
+ }
+
+ while (iters > 0 && (!zapb)) {
+ iters--,sp--;
+ if (iters > 0) {
+ zaps = str_get(afetch(ary,iters-1,FALSE));
+ zapb = (int) *zaps;
+ }
+ }
+#endif
}
- if (retary) {
- *ptrmaxsarg = iters + sargoff;
- sarg = (STR**)saferealloc((char*)(sarg - sargoff),
- (iters+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-
- for (i = 1; i <= iters; i++)
- sarg[i] = afetch(ary,i-1);
- *retary = sarg;
+ if (realarray) {
+ ary->ary_fill = sp;
+ if (gimme == G_ARRAY) {
+ sp++;
+ astore(stack, arglast[0] + 1 + sp, Nullstr);
+ Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
+ return arglast[0] + sp;
+ }
}
- return iters;
+ else {
+ if (gimme == G_ARRAY)
+ return sp;
+ }
+ sp = arglast[0] + 1;
+ str_numset(str,(double)iters);
+ STABSET(str);
+ st[sp] = str;
+ return sp;
}

My next step after the REXTEND workaround (R=real), is to benchmark this since its stable enough to run now.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Jun 3, 2014

From @bulk88

0001-vm-stacks.patch
From f689583c0fae18a7b64f4b41db36c14a1c9d39e6 Mon Sep 17 00:00:00 2001
From: Daniel Dragan <bulk88@hotmail.com>
Date: Tue, 3 Jun 2014 01:34:45 -0400
Subject: [PATCH] vm stacks

---
 embed.fnc      |    4 +++
 embed.h        |    4 +++
 perl.h         |    8 +++++-
 pp.c           |   18 +++++++-------
 pp.h           |   29 ++++++++++++++++++----
 pp_ctl.c       |   10 ++++++-
 proto.h        |    4 +++
 run.c          |   16 ++++++++++++
 scope.c        |   48 +++++++++++++++++++++++++++++++++++++
 sv.c           |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 win32/Makefile |    6 ++--
 win32/win32.c  |   46 +++++++++++++++++++++++++++++++++++
 win32/win32.h  |   17 +++++++++++++
 13 files changed, 256 insertions(+), 26 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index fc3ed95..1a99170 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -1678,6 +1678,10 @@ Ap	|struct perl_vars *|GetVars
 Ap	|struct perl_vars*|init_global_struct
 Ap	|void	|free_global_struct|NN struct perl_vars *plvarsp
 #endif
+#if defined(PERL_ALT_STACKS)
+pX	|int	|call_runops|
+pn	|DWORD	|fix_win32stacks|LPEXCEPTION_POINTERS exceptions
+#endif
 Ap	|int	|runops_standard
 Ap	|int	|runops_debug
 Afpd	|void	|sv_catpvf_mg	|NN SV *const sv|NN const char *const pat|...
diff --git a/embed.h b/embed.h
index b7a0290..bfe61e9 100644
--- a/embed.h
+++ b/embed.h
@@ -1355,6 +1355,10 @@
 #define malloc_good_size	Perl_malloc_good_size
 #define malloced_size		Perl_malloced_size
 #  endif
+#  if defined(PERL_ALT_STACKS)
+#define call_runops()		Perl_call_runops(aTHX)
+#define fix_win32stacks		Perl_fix_win32stacks
+#  endif
 #  if defined(PERL_CORE)
 #define opslab_force_free(a)	Perl_opslab_force_free(aTHX_ a)
 #define opslab_free(a)		Perl_opslab_free(aTHX_ a)
diff --git a/perl.h b/perl.h
index 6da39f3..5522a36 100644
--- a/perl.h
+++ b/perl.h
@@ -202,7 +202,13 @@
 #define MEMBER_TO_FPTR(name) name
 #endif /* !PERL_CORE */
 
-#define CALLRUNOPS  PL_runops
+//put call to func that has __try/__catch, then calls PL_runops here?
+#ifdef PERL_ALT_STACKS
+#  define CALLRUNOPS(x) Perl_call_runops(x)
+#else
+#error bad
+#  define CALLRUNOPS  PL_runops
+#endif
 
 #define CALLREGCOMP(sv, flags) Perl_pregcomp(aTHX_ (sv),(flags))
 
diff --git a/pp.c b/pp.c
index 04c1f29..4d0f95c 100644
--- a/pp.c
+++ b/pp.c
@@ -5543,7 +5543,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 
 	    /* skip the whitespace found last */
@@ -5584,7 +5584,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 	    s = m;
 	}
@@ -5601,9 +5601,9 @@ PP(pp_split)
 	if (!gimme_scalar) {
 	    const U32 items = limit - 1;
 	    if (items < slen)
-		EXTEND(SP, items);
+		REXTEND(SP, items);
 	    else
-		EXTEND(SP, slen);
+		REXTEND(SP, slen);
 	}
 
         if (do_utf8) {
@@ -5671,7 +5671,7 @@ PP(pp_split)
 		} else {
 		    dstr = newSVpvn_flags(s, m-s,
 					 (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		    XPUSHs(dstr);
+		    RXPUSHs(dstr);
 		}
 		/* The rx->minlen is in characters but we want to step
 		 * s ahead by bytes. */
@@ -5695,7 +5695,7 @@ PP(pp_split)
 		} else {
 		    dstr = newSVpvn_flags(s, m-s,
 					 (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		    XPUSHs(dstr);
+		    RXPUSHs(dstr);
 		}
 		/* The rx->minlen is in characters but we want to step
 		 * s ahead by bytes. */
@@ -5732,7 +5732,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 	    if (RX_NPARENS(rx)) {
 		I32 i;
@@ -5757,7 +5757,7 @@ PP(pp_split)
 			}
 			else
 			    dstr = &PL_sv_undef;  /* undef, not "" */
-			XPUSHs(dstr);
+			RXPUSHs(dstr);
 		    }
 
 		}
@@ -5777,7 +5777,7 @@ PP(pp_split)
 	if (!gimme_scalar) {
 	    const STRLEN l = strend - s;
 	    dstr = newSVpvn_flags(s, l, (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-	    XPUSHs(dstr);
+	    RXPUSHs(dstr);
 	}
 	iters++;
     }
diff --git a/pp.h b/pp.h
index 97738c2..bfc5b6e 100644
--- a/pp.h
+++ b/pp.h
@@ -270,24 +270,42 @@ Does not use C<TARG>.  See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
 =cut
 */
 
-#ifdef STRESS_REALLOC
-# define EXTEND(p,n)	(void)(sp = stack_grow(sp,p, (SSize_t)(n)))
+#ifndef PERL_ALT_STACKS
+#  ifdef STRESS_REALLOC
+#    define EXTEND(p,n)	(void)(sp = stack_grow(sp,p, (SSize_t)(n)))
 /* Same thing, but update mark register too. */
-# define MEXTEND(p,n)	STMT_START {					\
+#    define MEXTEND(p,n)	STMT_START {				\
 			    const int markoff = mark - PL_stack_base;	\
 			    sp = stack_grow(sp,p,(SSize_t) (n));	\
 			    mark = PL_stack_base + markoff;		\
 			} STMT_END
+#  else
+#    define EXTEND(p,n)   (void)(UNLIKELY(PL_stack_max - p < (SSize_t)(n)) &&     \
+			    (sp = stack_grow(sp,p, (SSize_t) (n))))
+
+/* Same thing, but update mark register too. */
+#    define MEXTEND(p,n)  STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
+                           const int markoff = mark - PL_stack_base;           \
+                           sp = stack_grow(sp,p,(SSize_t) (n));                \
+                           mark = PL_stack_base + markoff;                     \
+                       } } STMT_END
+#  endif
 #else
-# define EXTEND(p,n)   (void)(UNLIKELY(PL_stack_max - p < (SSize_t)(n)) &&     \
+#  ifdef STRESS_REALLOC
+#    error STRESS_REALLOC and PERL_ALT_STACKS not implemented
+#  else
+#    define EXTEND(p,n)   NOOP
+#    define MEXTEND(p,n)  NOOP
+#    define REXTEND(p,n)   (void)(UNLIKELY(PL_stack_max - p < (SSize_t)(n)) &&     \
 			    (sp = stack_grow(sp,p, (SSize_t) (n))))
 
 /* Same thing, but update mark register too. */
-# define MEXTEND(p,n)  STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
+#    define RMEXTEND(p,n)  STMT_START {if (UNLIKELY(PL_stack_max - p < (int)(n))) {\
                            const int markoff = mark - PL_stack_base;           \
                            sp = stack_grow(sp,p,(SSize_t) (n));                \
                            mark = PL_stack_base + markoff;                     \
                        } } STMT_END
+#  endif
 #endif
 
 #define PUSHs(s)	(*++sp = (s))
@@ -298,6 +316,7 @@ Does not use C<TARG>.  See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
 #define PUSHu(u)	STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END
 
 #define XPUSHs(s)	(EXTEND(sp,1), *++sp = (s))
+#define RXPUSHs(s)	(REXTEND(sp,1), *++sp = (s))
 #define XPUSHTARG	STMT_START { SvSETMAGIC(TARG); XPUSHs(TARG); } STMT_END
 #define XPUSHp(p,l)	STMT_START { sv_setpvn(TARG, (p), (l)); XPUSHTARG; } STMT_END
 #define XPUSHn(n)	STMT_START { sv_setnv(TARG, (NV)(n)); XPUSHTARG; } STMT_END
diff --git a/pp_ctl.c b/pp_ctl.c
index 380a7fe..2d4f8d2 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1001,8 +1001,14 @@ PP(pp_mapwhile)
 	    dst = (SP += shift);
 	    PL_markstack_ptr[-1] += shift;
 	    *PL_markstack_ptr += shift;
-	    while (count--)
-		*dst-- = *src--;
+            //copy upwards not downwards
+            if(count) {
+                SV** dst1 = dst;
+                SV** src1 = src;
+                dst1 -= (count-1);
+                src1 -= (count-1);
+                memcpy(dst1, src1, sizeof(SV**)*count);
+            }
 	}
 	/* copy the new items down to the destination list */
 	dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1;
diff --git a/proto.h b/proto.h
index f7716b5..f65f80c 100644
--- a/proto.h
+++ b/proto.h
@@ -5472,6 +5472,10 @@ PERL_CALLCONV MEM_SIZE	Perl_malloced_size(void *p)
 #if defined(NO_MATHOMS)
 /* PERL_CALLCONV void	Perl_sv_nounlocking(pTHX_ SV *sv); */
 #endif
+#if defined(PERL_ALT_STACKS)
+PERL_CALLCONV int	Perl_call_runops(pTHX);
+PERL_CALLCONV DWORD	Perl_fix_win32stacks(LPEXCEPTION_POINTERS exceptions);
+#endif
 #if defined(PERL_ANY_COW)
 PERL_CALLCONV SV*	Perl_sv_setsv_cow(pTHX_ SV* dstr, SV* sstr)
 			__attribute__nonnull__(pTHX_2);
diff --git a/run.c b/run.c
index ff3bc93..04f2673 100644
--- a/run.c
+++ b/run.c
@@ -48,6 +48,22 @@ Perl_runops_standard(pTHX)
     return 0;
 }
 
+#ifdef PERL_ALT_STACKS
+int
+Perl_call_runops(pTHX)
+{
+    __try {
+        return PL_runops(aTHX);
+    }
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+    croak_no_mem();
+}
+#endif
+
 /*
  * Local variables:
  * c-indentation-style: bsd
diff --git a/scope.c b/scope.c
index 07f24b7..06b54c3 100644
--- a/scope.c
+++ b/scope.c
@@ -56,7 +56,55 @@ Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems)
     Newx(si, 1, PERL_SI);
     si->si_stack = newAV();
     AvREAL_off(si->si_stack);
+#ifndef PERL_ALT_STACKS
     av_extend(si->si_stack, stitems > 0 ? stitems-1 : 0);
+#else
+    {
+    void *avarr;
+    void * avarr2;
+    void * toalloc;
+    Safefree(AvALLOC(si->si_stack));
+    AvALLOC(si->si_stack) = NULL;
+    AvARRAY(si->si_stack) = NULL;
+    AvMAX(si->si_stack) = SSize_t_MAX/sizeof(SV*);
+    //fprintf(stderr, "stack alloc NSI av=%x\n", si->si_stack);
+    avarr = VirtualAlloc(
+        NULL,
+        STACKMAX,
+        MEM_RESERVE,
+        PAGE_NOACCESS
+    );
+    if(!avarr) {
+        DWORD e = GetLastError();
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    //4096 (page size) should be constant or runtime lookup from Win32 API, for
+    //4096 on 32 and x64, 8K on ia64 http://blogs.msdn.com/b/oldnewthing/archive/2004/09/08/226797.aspx
+    if(! (avarr2 = VirtualAlloc(avarr,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE
+                   ))) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    (DWORD_PTR)toalloc = (DWORD_PTR)avarr+PERL_PAGESIZE;
+    if(!VirtualAlloc(toalloc,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE|PAGE_GUARD
+                   )) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    AvALLOC(si->si_stack) = (SV**)avarr;
+    AvARRAY(si->si_stack) = (SV**)avarr;
+    }
+#endif
     AvALLOC(si->si_stack)[0] = &PL_sv_undef;
     AvFILLp(si->si_stack) = 0;
     si->si_prev = 0;
diff --git a/sv.c b/sv.c
index d748d56..4baafdf 100644
--- a/sv.c
+++ b/sv.c
@@ -6430,7 +6430,20 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
 		    iter_sv = sv;
 		    goto get_next_sv; /* process this new sv */
 		}
-		Safefree(AvALLOC(av));
+                if(!AvREAL((const AV *)av) && AvMAX((const AV *)av) == SSize_t_MAX/sizeof(SV*)) {
+                    //fprintf(stderr, "stack dealloc av=%x\n", av);
+                    if(!VirtualFree(
+                        AvALLOC(av),
+                        0,
+                        MEM_RELEASE
+                        )) {
+                        fprintf(stderr, "VF failed %u\n", GetLastError());
+                        exit(1);
+                        }
+                }
+                else {
+                    Safefree(AvALLOC(av));
+                }
 	    }
 
 	    break;
@@ -6774,6 +6787,8 @@ Perl_sv_free(pTHX_ SV *const sv)
 /* Private helper function for SvREFCNT_dec().
  * Called with rc set to original SvREFCNT(sv), where rc == 0 or 1 */
 
+SV * watch_sv;
+
 void
 Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
 {
@@ -6781,6 +6796,9 @@ Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
 
     PERL_ARGS_ASSERT_SV_FREE2;
 
+    if( sv == watch_sv) {
+        DebugBreak();
+    }
     if (LIKELY( rc == 1 )) {
         /* normal case */
         SvREFCNT(sv) = 0;
@@ -12678,7 +12696,48 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 		    SSize_t items = AvFILLp((const AV *)sstr) + 1;
 
 		    src_ary = AvARRAY((const AV *)sstr);
-		    Newxz(dst_ary, AvMAX((const AV *)sstr)+1, SV*);
+		    if(!AvREAL((const AV *)sstr) && AvMAX((const AV *)sstr) == SSize_t_MAX/sizeof(SV*)) {
+			MEMORY_BASIC_INFORMATION mbi;
+			void * avarr;
+			DWORD_PTR toalloc;
+			void * avarr2;
+			//fprintf(stderr, "stack alloc S_sv_dup_common src av=%x dst av=%x\n", sstr, dstr);
+			if(VirtualQuery(src_ary,&mbi,sizeof(mbi)) != sizeof(mbi)){
+			    DebugBreak();
+			    fprintf(stderr, "VQ failed %u\n", GetLastError());
+			    exit(1);
+			}
+			avarr = VirtualAlloc(
+			    NULL,
+			    33554432, //2^25 32 MB
+			    MEM_RESERVE,
+			    PAGE_NOACCESS
+			);
+			if(!avarr) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			if(! (avarr2 = VirtualAlloc(avarr,
+				       mbi.RegionSize,
+				       MEM_COMMIT,
+				       PAGE_READWRITE
+				       ))) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			toalloc = (DWORD_PTR) avarr + mbi.RegionSize;
+			if(!VirtualAlloc(toalloc,
+				       4096,
+				       MEM_COMMIT,
+				       PAGE_READWRITE|PAGE_GUARD
+				       )) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			dst_ary = avarr;
+		    } else {
+			Newxz(dst_ary, AvMAX((const AV *)sstr)+1, SV*);
+		    }
 		    ptr_table_store(PL_ptr_table, src_ary, dst_ary);
 		    AvARRAY(MUTABLE_AV(dstr)) = dst_ary;
 		    AvALLOC((const AV *)dstr) = dst_ary;
@@ -12690,10 +12749,11 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 			while (items-- > 0)
 			    *dst_ary++ = sv_dup(*src_ary++, param);
 		    }
-		    items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr);
-		    while (items-- > 0) {
-			*dst_ary++ = &PL_sv_undef;
-		    }
+                    //is this really needed? This is uninit space I think
+		//    items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr);
+		//    while (items-- > 0) {
+		//	*dst_ary++ = &PL_sv_undef;
+		//    }
 		}
 		else {
 		    AvARRAY(MUTABLE_AV(dstr))	= NULL;
diff --git a/win32/Makefile b/win32/Makefile
index 8b1847c..8097e1e 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -220,7 +220,7 @@ BUILDOPT	= $(BUILDOPTEXTRA)
 # mode script reading (and break some DATA filehandle functionality)
 # please check first if an updated ByteLoader isn't available on CPAN.
 #
-BUILDOPT	= $(BUILDOPT) -DPERL_TEXTMODE_SCRIPTS -DPERL_HASH_FUNC_ONE_AT_A_TIME
+BUILDOPT	= $(BUILDOPT) -DPERL_TEXTMODE_SCRIPTS -DPERL_HASH_FUNC_ONE_AT_A_TIME -DPERL_ALT_STACKS
 
 #
 # specify semicolon-separated list of extra directories that modules will
@@ -1004,10 +1004,10 @@ $(MINIDIR) :
 	if not exist "$(MINIDIR)" mkdir "$(MINIDIR)"
 
 $(MINICORE_OBJ) : $(CORE_NOCFG_H)
-	$(CC) -c $(CFLAGS) -DPERL_EXTERNAL_GLOB -DPERL_IS_MINIPERL $(OBJOUT_FLAG)$@ ..\$(*F).c
+	$(CC) -c $(CFLAGS) -DPERL_EXTERNAL_GLOB -DPERL_IS_MINIPERL -DPERL_ALT_STACKS $(OBJOUT_FLAG)$@ ..\$(*F).c
 
 $(MINIWIN32_OBJ) : $(CORE_NOCFG_H)
-	$(CC) -c $(CFLAGS) -DPERL_IS_MINIPERL $(OBJOUT_FLAG)$@ $(*F).c
+	$(CC) -c $(CFLAGS) -DPERL_IS_MINIPERL -DPERL_ALT_STACKS $(OBJOUT_FLAG)$@ $(*F).c
 
 # -DPERL_IMPLICIT_SYS needs C++ for perllib.c
 # This is the only file that depends on perlhost.h, vmem.h, and vdir.h
diff --git a/win32/win32.c b/win32/win32.c
index cd594ca..191fcc3 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4560,6 +4560,52 @@ win32_create_message_window(void)
                         0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
 }
 
+#ifdef PERL_ALT_STACKS
+DWORD
+Perl_fix_win32stacks(LPEXCEPTION_POINTERS exceptions)
+{
+    dTHX;
+    MEMORY_BASIC_INFORMATION mbi;
+    DWORD_PTR newalloc;
+    assert(exceptions->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION
+          && exceptions->ExceptionRecord->ExceptionFlags == 0);
+//needs bounds checks to make sure the STATUS_GUARD_PAGE_VIOLATION is for Perl stack and not some other c lib doing the same thing
+    /* ExceptionAddress is EIP/ * to machine code where fault happened, its not
+      interesting */
+    /* ExceptionFlags has to be zero, or the exception is not resumable, so there
+      is no point in checking it */
+    if(exceptions->ExceptionRecord->NumberParameters == 2
+       && (exceptions->ExceptionRecord->ExceptionInformation[0] == 0 /* read fault */
+       || exceptions->ExceptionRecord->ExceptionInformation[0] == 1) /* write failt */
+       && exceptions->ExceptionRecord->ExceptionInformation[1] >= (ULONG_PTR)PL_stack_base && /* fault addr >= stack bottom */
+//should this catch something beyond the alloc or let it pass through, and catch how far beyond the alloc?
+       exceptions->ExceptionRecord->ExceptionInformation[1] <= (ULONG_PTR)PL_stack_base + STACKMAX) {
+    //this is inefficient, these things should be stored somewhere in interp struct
+    if(VirtualQuery(PL_stack_base,&mbi,sizeof(mbi)) != sizeof(mbi)){
+        DebugBreak();
+        fprintf(stderr, "VQ failed %u\n", GetLastError());
+        exit(1);
+    }
+    assert(PL_stack_base == PL_stack_base && PL_stack_base == AvARRAY(PL_curstack));
+    newalloc = (DWORD_PTR)mbi.AllocationBase+(DWORD_PTR)mbi.RegionSize;
+    if(!VirtualAlloc(newalloc,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE|PAGE_GUARD
+                   )) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+
+    return EXCEPTION_CONTINUE_EXECUTION;
+    }
+    else { /* fault address and exception isn't from Perl */
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+}
+#endif
+
 #ifdef HAVE_INTERP_INTERN
 
 static void
diff --git a/win32/win32.h b/win32/win32.h
index bfb276f..d61f089 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -225,6 +225,23 @@ struct utsname {
 #  define WNOHANG	1
 #endif
 
+#ifndef PERL_PAGESIZE
+#  if defined(PAGE_SIZE)
+#    define PERL_PAGESIZE PAGE_SIZE
+#  elif defined(_M_IA64) || defined(__IA64__)
+/* http://blogs.msdn.com/b/oldnewthing/archive/2004/09/08/226797.aspx */
+#    define PERL_PAGESIZE 8192
+#  elif defined(_M_IX86) || defined(_M_X64) || defined (__i386__) || defined(__x86_64__)
+#    define PERL_PAGESIZE 4096
+#  else
+#    error Unknown page size (ARM ?)
+#  endif
+#endif
+
+#ifdef PERL_ALT_STACKS
+#  define STACKMAX 0x1F00000
+#endif
+
 #define PERL_GET_CONTEXT_DEFINED
 
 /* Compiler-specific stuff. */
-- 
1.7.9.msysgit.0

@p5pRT
Copy link
Author

p5pRT commented Jun 4, 2014

From @bulk88

On Mon Jun 02 22​:54​:57 2014, bulk88 wrote​:

My next step after the REXTEND workaround (R=real), is to benchmark
this since its stable enough to run now.

noextend (self allocating stack) perl is reliable 2% faster on perlbench


  ext noext ext2 noext2
  --- ----- ---- ------
arith/mixed 100 98 100 98
arith/trig 100 98 100 98
array/copy 100 99 101 99
array/foreach 100 101 99 101
array/index 100 110 100 109
array/pop 100 104 101 102
array/shift 100 102 101 101
array/sort-num 100 101 101 102
array/sort 100 97 100 98
call/0arg 100 103 98 104
call/1arg 100 100 98 99
call/2arg 100 109 103 109
call/9arg 100 101 100 102
call/empty 100 98 100 99
call/fib 100 99 99 99
call/method 100 99 101 99
call/wantarray 100 102 100 101
hash/copy 100 91 99 95
hash/each 100 102 101 101
hash/foreach-sort 100 101 100 101
hash/foreach 100 101 98 101
hash/get 100 103 103 103
hash/set 100 102 98 104
loop/for-c 100 104 102 105
loop/for-range-const 100 106 100 107
loop/for-range 100 116 99 118
loop/getline 100 101 100 101
loop/while-my 100 101 99 102
loop/while 100 107 100 106
re/const 100 99 100 99
re/w 100 100 101 99
startup/fewmod - - - -
startup/lotsofsub - - - -
startup/noprog 100 102 101 114
string/base64 100 99 100 100
string/htmlparser 100 99 100 99
string/index-const 100 90 101 95
string/index-var 100 126 99 127
string/ipol 100 96 101 95
string/tr 100 101 101 101

AVERAGE 100 102 100 102

Results saved in file​:///C|/sources/perlbench/benchres-004/index.html

C​:\sources\perlbench>perl perlbench-run -c 100000 noext=C​:\perl521\noextend\bin\


Now to reverse the order of the perls, to squeeze out outside effects


  noext ext noext2 ext2
  ----- --- ------ ----
arith/mixed 100 102 100 102
arith/trig 100 102 100 102
array/copy 100 101 101 101
array/foreach 100 98 101 98
array/index 100 91 101 92
array/pop 100 98 99 99
array/shift 100 99 100 100
array/sort-num 100 99 100 100
array/sort 100 103 100 103
call/0arg 100 95 99 95
call/1arg 100 96 99 99
call/2arg 100 94 100 91
call/9arg 100 96 99 97
call/empty 100 102 100 102
call/fib 100 96 100 101
call/method 100 103 102 103
call/wantarray 100 99 101 99
hash/copy 100 99 108 102
hash/each 100 99 99 99
hash/foreach-sort 100 98 99 98
hash/foreach 100 100 100 99
hash/get 100 104 103 101
hash/set 100 99 99 98
loop/for-c 100 96 101 97
loop/for-range-const 100 93 110 93
loop/for-range 100 84 99 84
loop/getline 100 99 99 98
loop/while-my 100 98 101 97
loop/while 100 94 101 94
re/const 100 101 99 101
re/w 100 101 101 101
startup/fewmod - - 100 -
startup/lotsofsub - - - -
startup/noprog 100 91 91 87
string/base64 100 100 100 101
string/htmlparser 100 100 99 100
string/index-const 100 110 106 110
string/index-var 100 78 100 78
string/ipol 100 105 98 105
string/tr 100 99 100 99

AVERAGE 100 98 100 98

Results saved in file​:///C|/sources/perlbench/benchres-005/index.html

C​:\sources\perlbench>


the largest difference was string/index-var at 26% faster. Many of the tests are noise, since they are less than 2% faster or upto 2% slower, and testing regular perl (regular malloc stack) against regular perlshows it can be 1-2% faster, which means that is noise. The largest perf decrease with no extend perl was 5% slower on string/index-const and string/ipol.

This means more optimizing since I am looking things up with syscalls instead of caching them. Or a 4096 byte initial stack is too small and needs to be 8k. Or EXTEND() needs to be similar to win32 alloca and do something special if the extend request is more than 4096/sizeof(SV*) to do just 1 VM syscall to get multiple pages instead of address faulting and SEH exception dispatch and VM syscalls numerous times (once for each page).

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Jun 5, 2014

From @bulk88

On Tue Jun 03 17​:46​:19 2014, bulk88 wrote​:

the largest difference was string/index-var at 26% faster. Many of the
tests are noise, since they are less than 2% faster or upto 2% slower,
and testing regular perl (regular malloc stack) against regular
perlshows it can be 1-2% faster, which means that is noise. The
largest perf decrease with no extend perl was 5% slower on
string/index-const and string/ipol.

This means more optimizing since I am looking things up with syscalls
instead of caching them. Or a 4096 byte initial stack is too small and
needs to be 8k. Or EXTEND() needs to be similar to win32 alloca and do
something special if the extend request is more than 4096/sizeof(SV*)
to do just 1 VM syscall to get multiple pages instead of address
faulting and SEH exception dispatch and VM syscalls numerous times
(once for each page).

With some changes, string/index-const is now faster, but some other things are slower and more jittery. "hash/get" and "hash/copy" was 5% faster on the 2nd run of the same binary than on the first run.


  ext noext ext2 noext2
  --- ----- ---- ------
arith/mixed 100 97 100 97
arith/trig 100 100 100 99
array/copy 100 100 101 100
array/foreach 100 99 101 101
array/index 100 105 100 104
array/pop 100 102 100 103
array/shift 100 101 100 102
array/sort-num 100 100 100 100
array/sort 100 99 100 100
call/0arg 100 99 100 100
call/1arg 100 101 101 102
call/2arg 100 99 100 100
call/9arg 100 113 100 114
call/empty 100 103 98 102
call/fib 100 107 102 108
call/method 100 102 100 102
call/wantarray 100 104 99 104
hash/copy 100 94 100 100
hash/each 100 108 99 107
hash/foreach-sort 100 101 100 101
hash/foreach 100 94 100 94
hash/get 100 119 105 119
hash/set 100 101 102 102
loop/for-c 100 95 100 94
loop/for-range-const 100 104 100 104
loop/for-range 100 104 101 103
loop/getline 100 97 100 102
loop/while-my 100 104 99 104
loop/while 100 105 100 104
re/const 100 102 100 103
re/w 100 103 100 103
startup/fewmod 100 112 - 81
startup/lotsofsub - - - -
startup/noprog 100 95 98 93
string/base64 100 100 99 101
string/htmlparser 100 97 101 97
string/index-const 100 105 95 106
string/index-var 100 101 99 101
string/ipol 100 96 100 95
string/tr 100 93 101 94

AVERAGE 100 102 100 101

Results saved in file​:///C|/sources/perlbench/benchres-006/index.html

  noext ext noext2 ext2
  ----- --- ------ ----
arith/mixed 100 103 100 103
arith/trig 100 102 100 101
array/copy 100 100 100 99
array/foreach 100 101 101 101
array/index 100 96 100 95
array/pop 100 97 99 97
array/shift 100 99 100 99
array/sort-num 100 101 100 100
array/sort 100 101 100 101
call/0arg 100 101 99 100
call/1arg 100 99 100 99
call/2arg 100 102 99 101
call/9arg 100 89 100 89
call/empty 100 96 99 96
call/fib 100 94 100 95
call/method 100 97 100 97
call/wantarray 100 96 100 96
hash/copy 100 107 107 112
hash/each 100 93 99 94
hash/foreach-sort 100 100 101 102
hash/foreach 100 106 100 107
hash/get 100 88 101 87
hash/set 100 99 100 99
loop/for-c 100 107 101 106
loop/for-range-const 100 95 98 95
loop/for-range 100 97 101 97
loop/getline 100 101 95 101
loop/while-my 100 97 99 96
loop/while 100 95 98 94
re/const 100 98 99 97
re/w 100 98 100 98
startup/fewmod 100 111 71 111
startup/lotsofsub - - - -
startup/noprog 100 104 98 111
string/base64 100 98 100 99
string/htmlparser 100 104 100 103
string/index-const 100 94 100 90
string/index-var 100 99 100 99
string/ipol 100 99 100 100
string/tr 100 110 101 110

AVERAGE 100 99 99 99


I moved the try/catch to a more global location, thinking the overhead up setting up the Win32 OS exception handler and removing it was causing overhead. Apparently, runops_standard is entered and left 100s-1000s of times in a typical process's life.


  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x027fcb94, volatile long flags=13) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=2, av * paramList=0x027fcc04) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=37, const char * const fullname=0x02808c40, gv * const gv=0x027fcc14, cv * const cv=0x027fcb94) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=37, op * o=0x02808a50, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02808a70, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00000000, int aver=1, long floor=37, op * version=0x00000000, op * idop=0x00000000, op * arg=0x02808848) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_parse_body(interpreter * my_perl=0x00000000, char * * env=0x00362a20, void (interpreter *)* xsinit=0x280b4ca8) Line 2300 + 0xd C
  perl521.dll!perl_parse(interpreter * my_perl=0x00364694, void (interpreter *)* xsinit=0x280b4ca8, int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 1610 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 254 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x027fcd54, volatile long flags=13) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=9, av * paramList=0x027fccc4) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=163, const char * const fullname=0x02808c40, gv * const gv=0x027fcd94, cv * const cv=0x027fcd54) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=163, op * o=0x028103e8, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02810004, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00000000, int aver=1, long floor=163, op * version=0x00000000, op * idop=0x027fcce4, op * arg=0x00000000) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_doeval(interpreter * my_perl=0x00364694, int gimme=2, cv * outside=0x00000000, unsigned long seq=0, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x0280546c) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x027fcd54, volatile long flags=13) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=2, av * paramList=0x027fcc04) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=37, const char * const fullname=0x02808c40, gv * const gv=0x027fcc14, cv * const cv=0x027fcb94) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=37, op * o=0x02808a50, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02808a70, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00000000, int aver=1, long floor=37, op * version=0x00000000, op * idop=0x00000000, op * arg=0x02808848) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_parse_body(interpreter * my_perl=0x00000000, char * * env=0x00362a20, void (interpreter *)* xsinit=0x280b4ca8) Line 2300 + 0xd C
  perl521.dll!perl_parse(interpreter * my_perl=0x00364694, void (interpreter *)* xsinit=0x280b4ca8, int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 1610 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 254 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 C
  perl521.dll!S_fold_constants(interpreter * my_perl=0x00364694, op * o=0x02816080) Line 3598 C
  perl521.dll!Perl_newUNOP(interpreter * my_perl=0x00364694, long type=20, long flags=0, op * first=0x028160bc) Line 4296 + 0x16 C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=6) Line 1200 C
  perl521.dll!S_doeval(interpreter * my_perl=0x047f0004, int gimme=2, cv * outside=0x00364694, unsigned long seq=2, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x0280988c) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x00000006, volatile long flags=0) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=9, av * paramList=0x027fccc4) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=148, const char * const fullname=0x02808c40, gv * const gv=0x027fcd94, cv * const cv=0x027fcd64) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=148, op * o=0x0281174c, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x0281176c, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00364694, int aver=1, long floor=148, op * version=0x00000000, op * idop=0x00000000, op * arg=0x00000000) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_doeval(interpreter * my_perl=0x047f0004, int gimme=2, cv * outside=0x00364694, unsigned long seq=0, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x0280546c) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x00000006, volatile long flags=0) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=2, av * paramList=0x027fcc04) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=37, const char * const fullname=0x02808c40, gv * const gv=0x027fcc14, cv * const cv=0x027fcb94) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=37, op * o=0x02808a50, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02808a70, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00364694, int aver=1, long floor=37, op * version=0x00000000, op * idop=0x00000000, op * arg=0x02808848) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_parse_body(interpreter * my_perl=0x00364694, char * * env=0x00362a20, void (interpreter *)* xsinit=0x280b4ca8) Line 2300 + 0xd C
  perl521.dll!perl_parse(interpreter * my_perl=0x00364694, void (interpreter *)* xsinit=0x280b4ca8, int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 1610 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 254 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 38 C
  perl521.dll!S_fold_constants(interpreter * my_perl=0x00364694, op * o=0x02835adc) Line 3598 C
  perl521.dll!Perl_convert(interpreter * my_perl=0x00364694, long type=68, long flags=0, op * o=0x0012f2cc) Line 3741 + 0x16 C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=68) Line 865 C
  perl521.dll!S_doeval(interpreter * my_perl=0x0012f2d0, int gimme=2, cv * outside=0x0012f2cc, unsigned long seq=100, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x02820dd4) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x066f0000, sv * sv=0x02832768, volatile long flags=42149792) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=17, av * paramList=0x0282491c) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=301, const char * const fullname=0x02808c40, gv * const gv=0x028249fc, cv * const cv=0x0282499c) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=301, op * o=0x02832724, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02832744, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x0012f2cc, int aver=1, long floor=301, op * version=0x00000000, op * idop=0x00000000, op * arg=0x00000000) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_doeval(interpreter * my_perl=0x0012f2d0, int gimme=2, cv * outside=0x0012f2cc, unsigned long seq=99, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x0280a3e4) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x066f0000, sv * sv=0x02832768, volatile long flags=42149792) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=10, av * paramList=0x027fccf4) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=190, const char * const fullname=0x02808c40, gv * const gv=0x0282423c, cv * const cv=0x0282467c) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=190, op * o=0x02809da4, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02809dc4, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x0012f2cc, int aver=1, long floor=190, op * version=0x00000000, op * idop=0x00000000, op * arg=0x00000000) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_doeval(interpreter * my_perl=0x0012f2d0, int gimme=2, cv * outside=0x0012f2cc, unsigned long seq=25, hv * hh=0x00000000) Line 3504 C
  perl521.dll!Perl_pp_require(interpreter * my_perl=0x0280988c) Line 4161 + 0x21 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x066f0000, sv * sv=0x02832768, volatile long flags=42149792) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=2, av * paramList=0x027fcc04) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=37, const char * const fullname=0x02808c40, gv * const gv=0x027fcc14, cv * const cv=0x027fcb94) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=37, op * o=0x02808a50, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02808a70, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x0012f2cc, int aver=1, long floor=37, op * version=0x00000000, op * idop=0x00000000, op * arg=0x02808848) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_parse_body(interpreter * my_perl=0x0012f2cc, char * * env=0x00362a20, void (interpreter *)* xsinit=0x280b4ca8) Line 2300 + 0xd C
  perl521.dll!perl_parse(interpreter * my_perl=0x00364694, void (interpreter *)* xsinit=0x280b4ca8, int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 1610 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 254 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 38 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x02869da4, volatile long flags=4098) Line 2758 + 0x20 C
  perl521.dll!Perl_magic_methcall(interpreter * my_perl=0x00000000, sv * sv=0x02838b44, const magic * mg=0x02809da4, sv * meth=0x02869da4, unsigned long flags=0, unsigned long argc=0, ...) Line 1810 + 0xe C
  perl521.dll!S_magic_methcall1(interpreter * my_perl=0x0012f808, sv * sv=0x02838b44, const magic * mg=0x00364694, sv * meth=0x02869da4, unsigned long flags=0, int n=1, sv * val=0x00000000) Line 1845 + 0x17 C
  perl521.dll!S_magic_methpack(interpreter * my_perl=0x00000000, sv * sv=0x02838b44, const magic * mg=0x00364694, sv * meth=0x02869da4) Line 1856 + 0x15 C
  perl521.dll!Perl_magic_getpack(interpreter * my_perl=0x00364694, sv * sv=0x02838b44, magic * mg=0x02809da4) Line 1869 + 0x2f C
  perl521.dll!Perl_mg_get(interpreter * my_perl=0x00364694, sv * sv=0x02838b44) Line 205 C
  perl521.dll!Perl_sv_setsv_flags(interpreter * my_perl=0x00364694, sv * dstr=0x0282491c, sv * sstr=0x0000000a, const long flags=1538) Line 4237 C
  perl521.dll!Perl_pp_aassign(interpreter * my_perl=0x028f000c) Line 1175 + 0xe C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!Perl_call_sv(interpreter * my_perl=0x00364694, sv * sv=0x02869da4, volatile long flags=4098) Line 2773 + 0xc C
  perl521.dll!Perl_call_list(interpreter * my_perl=0x00364694, long oldscope=2, av * paramList=0x027fcc04) Line 4891 C
  perl521.dll!S_process_special_blocks(interpreter * my_perl=0x00070023, long floor=37, const char * const fullname=0x02808c40, gv * const gv=0x027fcc14, cv * const cv=0x027fcb94) Line 8121 C
  perl521.dll!Perl_newATTRSUB_x(interpreter * my_perl=0x00000000, long floor=37, op * o=0x02808a50, op * proto=0x00000000, void * attrs=0x2802d28c, op * block=0x02808a70, char o_is_gv=0) Line 8081 + 0x13 C
  perl521.dll!Perl_utilize(interpreter * my_perl=0x00000000, int aver=1, long floor=37, op * version=0x00000000, op * idop=0x00000000, op * arg=0x02808848) Line 5447 + 0x7b C
  perl521.dll!Perl_yyparse(interpreter * my_perl=0x00364694, int gramtype=1) Line 398 + 0x16 C
  perl521.dll!S_parse_body(interpreter * my_perl=0x00000000, char * * env=0x00362a20, void (interpreter *)* xsinit=0x280b4ca8) Line 2300 + 0xd C
  perl521.dll!perl_parse(interpreter * my_perl=0x00364694, void (interpreter *)* xsinit=0x280b4ca8, int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 1610 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 254 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


And after all that painful stuff above, runops is called for one final time as


  perl521.dll!Perl_pp_leavesub(interpreter * my_perl=0x00364694) Line 2463 + 0x1 C
  perl521.dll!Perl_runops_standard(interpreter * my_perl=0x00364694) Line 42 + 0x4 C
  perl521.dll!S_run_body(interpreter * my_perl=0x7c36b01a, long oldscope=1) Line 2458 + 0xa C
  perl521.dll!perl_run(interpreter * my_perl=0x00364694) Line 2374 + 0x8 C
  perl521.dll!RunPerl(int argc=2, char * * argv=0x00362478, char * * env=0x00362a20) Line 261 + 0x8 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23


But it might not be the source of all slowness, since some things improved, and some got worse.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Jun 5, 2014

From @bulk88

0001-vm-stacks.patch
From 7c72fda8dd4884b792056663444bdfaa8227a30b Mon Sep 17 00:00:00 2001
From: Daniel Dragan <bulk88@hotmail.com>
Date: Thu, 5 Jun 2014 18:35:54 -0400
Subject: [PATCH] vm stacks

moved try catch to a more global location
---
 dist/threads/threads.xs |   13 ++++++++++
 embed.fnc               |    8 +++++-
 embed.h                 |    8 ++++++
 makedef.pl              |    6 ++++
 miniperlmain.c          |   13 ++++++++++
 perl.h                  |   10 +++++++
 pp.c                    |   18 +++++++-------
 pp.h                    |   38 ++++++++++++++++++++++++----
 pp_ctl.c                |   10 ++++++-
 proto.h                 |    8 ++++++
 run.c                   |   18 +++++++++++++
 scope.c                 |   48 ++++++++++++++++++++++++++++++++++++
 sv.c                    |   62 +++++++++++++++++++++++++++++++++++++++++++++++
 t/op/threads.t          |    2 +-
 win32/Makefile          |   19 ++++++++++++++
 win32/perlhost.h        |   13 ++++++++++
 win32/perllib.c         |   13 ++++++++++
 win32/win32.c           |   46 ++++++++++++++++++++++++++++++++++
 win32/win32.h           |   20 +++++++++++++++
 19 files changed, 354 insertions(+), 19 deletions(-)

diff --git a/dist/threads/threads.xs b/dist/threads/threads.xs
index 6175ba7..f31c27b 100644
--- a/dist/threads/threads.xs
+++ b/dist/threads/threads.xs
@@ -468,6 +468,9 @@ STATIC void *
 S_ithread_run(void * arg)
 #endif
 {
+#ifdef PERL_ALT_STACKS
+__try {
+#endif
     ithread *thread = (ithread *)arg;
     int jmp_rc = 0;
     I32 oldscope;
@@ -637,6 +640,16 @@ S_ithread_run(void * arg)
 #else
     return (0);
 #endif
+#ifdef PERL_ALT_STACKS
+}
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+Perl_croak_no_mem();
+#endif
+
 }
 
 
diff --git a/embed.fnc b/embed.fnc
index c820457..e1a14e3 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -273,7 +273,7 @@ Aprd	|void	|vcroak		|NULLOK const char* pat|NULLOK va_list* args
 Anprd	|void	|croak_no_modify
 Anprd	|void	|croak_xs_usage	|NN const CV *const cv \
 				|NN const char *const params
-npr	|void	|croak_no_mem
+nprX	|void	|croak_no_mem
 nprX	|void	|croak_popstack
 #if defined(WIN32)
 norx	|void	|win32_croak_not_implemented|NN const char * fname
@@ -1686,6 +1686,12 @@ Ap	|struct perl_vars *|GetVars
 Ap	|struct perl_vars*|init_global_struct
 Ap	|void	|free_global_struct|NN struct perl_vars *plvarsp
 #endif
+#if defined(PERL_ALT_STACKS)
+#if 0
+pX	|int	|call_runops|
+#endif
+pnX	|DWORD	|fix_win32stacks|LPEXCEPTION_POINTERS exceptions
+#endif
 Ap	|int	|runops_standard
 Ap	|int	|runops_debug
 Afpd	|void	|sv_catpvf_mg	|NN SV *const sv|NN const char *const pat|...
diff --git a/embed.h b/embed.h
index ca1b91b..614267d 100644
--- a/embed.h
+++ b/embed.h
@@ -1330,6 +1330,11 @@
 #  if !defined(WIN32)
 #define do_exec3(a,b,c)		Perl_do_exec3(aTHX_ a,b,c)
 #  endif
+#  if 0
+#    if defined(PERL_ALT_STACKS)
+#define call_runops()		Perl_call_runops(aTHX)
+#    endif
+#  endif
 #  if defined(DEBUGGING)
 #define get_debug_opts(a,b)	Perl_get_debug_opts(aTHX_ a,b)
 #    if defined(PERL_IN_PAD_C)
@@ -1361,6 +1366,9 @@
 #define malloc_good_size	Perl_malloc_good_size
 #define malloced_size		Perl_malloced_size
 #  endif
+#  if defined(PERL_ALT_STACKS)
+#define fix_win32stacks		Perl_fix_win32stacks
+#  endif
 #  if defined(PERL_CORE)
 #define opslab_force_free(a)	Perl_opslab_force_free(aTHX_ a)
 #define opslab_free(a)		Perl_opslab_free(aTHX_ a)
diff --git a/makedef.pl b/makedef.pl
index 8b972a4..8d32206 100644
--- a/makedef.pl
+++ b/makedef.pl
@@ -535,6 +535,12 @@ if ($define{HAS_SIGNBIT}) {
     ++$skip{Perl_signbit};
 }
 
+unless ($define{PERL_ALT_STACKS}) {
+    ++$skip{Perl_call_runops};
+    ++$skip{Perl_fix_win32stacks};
+}
+++$skip{Perl_call_runops}; #obsolete
+
 if ($define{'PERL_GLOBAL_STRUCT'}) {
     readvar('perlvars.h', \%skip);
     # This seems like the least ugly way to cope with the fact that PL_sh_path
diff --git a/miniperlmain.c b/miniperlmain.c
index f22dcbb..0a1da2c 100644
--- a/miniperlmain.c
+++ b/miniperlmain.c
@@ -92,6 +92,9 @@ main(int argc, char **argv, char **env)
     PERL_SYS_INIT3(&argc,&argv,&env);
 #endif
 
+#ifdef PERL_ALT_STACKS
+__try {
+#endif
 #if defined(USE_ITHREADS)
     /* XXX Ideally, this should really be happening in perl_alloc() or
      * perl_construct() to keep libperl.a transparently fork()-safe.
@@ -163,6 +166,16 @@ main(int argc, char **argv, char **env)
 
     exit(exitstatus);
     return exitstatus;
+#ifdef PERL_ALT_STACKS
+}
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+croak_no_mem();
+#endif
+
 }
 
 /* Register any extra external extensions */
diff --git a/perl.h b/perl.h
index 7338f61..df77f5e 100644
--- a/perl.h
+++ b/perl.h
@@ -202,6 +202,13 @@
 #define MEMBER_TO_FPTR(name) name
 #endif /* !PERL_CORE */
 
+//put call to func that has __try/__catch, then calls PL_runops here?
+//#ifdef PERL_ALT_STACKS
+//#  define CALLRUNOPS(x) Perl_call_runops(x)
+//#else
+//#  define CALLRUNOPS  PL_runops
+//#endif
+
 #define CALLRUNOPS  PL_runops
 
 #define CALLREGCOMP(sv, flags) Perl_pregcomp(aTHX_ (sv),(flags))
@@ -4624,6 +4631,9 @@ EXTCONST char PL_bincompat_options[] =
 #  ifdef PERLIO_LAYERS
 			     " PERLIO_LAYERS"
 #  endif
+#  ifdef PERL_ALT_STACKS
+			     " PERL_ALT_STACKS"
+#  endif
 #  ifdef PERL_DEBUG_READONLY_COW
 			     " PERL_DEBUG_READONLY_COW"
 #  endif
diff --git a/pp.c b/pp.c
index 11119a2..141ec09 100644
--- a/pp.c
+++ b/pp.c
@@ -5547,7 +5547,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 
 	    /* skip the whitespace found last */
@@ -5588,7 +5588,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 	    s = m;
 	}
@@ -5605,9 +5605,9 @@ PP(pp_split)
 	if (!gimme_scalar) {
 	    const U32 items = limit - 1;
 	    if (items < slen)
-		EXTEND(SP, items);
+		REXTEND(SP, items);
 	    else
-		EXTEND(SP, slen);
+		REXTEND(SP, slen);
 	}
 
         if (do_utf8) {
@@ -5675,7 +5675,7 @@ PP(pp_split)
 		} else {
 		    dstr = newSVpvn_flags(s, m-s,
 					 (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		    XPUSHs(dstr);
+		    RXPUSHs(dstr);
 		}
 		/* The rx->minlen is in characters but we want to step
 		 * s ahead by bytes. */
@@ -5699,7 +5699,7 @@ PP(pp_split)
 		} else {
 		    dstr = newSVpvn_flags(s, m-s,
 					 (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		    XPUSHs(dstr);
+		    RXPUSHs(dstr);
 		}
 		/* The rx->minlen is in characters but we want to step
 		 * s ahead by bytes. */
@@ -5736,7 +5736,7 @@ PP(pp_split)
 	    } else {
 		dstr = newSVpvn_flags(s, m-s,
 				      (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-		XPUSHs(dstr);
+		RXPUSHs(dstr);
 	    }
 	    if (RX_NPARENS(rx)) {
 		I32 i;
@@ -5761,7 +5761,7 @@ PP(pp_split)
 			}
 			else
 			    dstr = &PL_sv_undef;  /* undef, not "" */
-			XPUSHs(dstr);
+			RXPUSHs(dstr);
 		    }
 
 		}
@@ -5781,7 +5781,7 @@ PP(pp_split)
 	if (!gimme_scalar) {
 	    const STRLEN l = strend - s;
 	    dstr = newSVpvn_flags(s, l, (do_utf8 ? SVf_UTF8 : 0) | make_mortal);
-	    XPUSHs(dstr);
+	    RXPUSHs(dstr);
 	}
 	iters++;
     }
diff --git a/pp.h b/pp.h
index a7e936c..ff90fce 100644
--- a/pp.h
+++ b/pp.h
@@ -271,33 +271,58 @@ Does not use C<TARG>.  See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
 =cut
 */
 
-#ifdef STRESS_REALLOC
-# define EXTEND(p,n)   STMT_START {                                     \
+#ifndef PERL_ALT_STACKS
+#  ifdef STRESS_REALLOC
+#    define EXTEND(p,n)   STMT_START {                                  \
                            sp = stack_grow(sp,p,(SSize_t) (n));         \
                            PERL_UNUSED_VAR(sp);                         \
                        } STMT_END
 /* Same thing, but update mark register too. */
-# define MEXTEND(p,n)   STMT_START {                                    \
+#     define MEXTEND(p,n)   STMT_START {                                \
                             const int markoff = mark - PL_stack_base;   \
                             sp = stack_grow(sp,p,(SSize_t) (n));        \
                             mark = PL_stack_base + markoff;             \
                             PERL_UNUSED_VAR(sp);                        \
                         } STMT_END
+#  else
+#    define EXTEND(p,n)   STMT_START {                                  \
+                         if (UNLIKELY(PL_stack_max - p < (int)(n))) {   \
+                           sp = stack_grow(sp,p,(SSize_t) (n));         \
+                           PERL_UNUSED_VAR(sp);                         \
+                         } } STMT_END
+/* Same thing, but update mark register too. */
+#    define MEXTEND(p,n)  STMT_START {                                  \
+                         if (UNLIKELY(PL_stack_max - p < (int)(n))) {   \
+                           const int markoff = mark - PL_stack_base;    \
+                           sp = stack_grow(sp,p,(SSize_t) (n));         \
+                           mark = PL_stack_base + markoff;              \
+                           PERL_UNUSED_VAR(sp);                         \
+                         } } STMT_END
+#  endif /* STRESS_REALLOC */
+#  define REXTEND(p,n) EXTEND(p,n)
+#  define RMEXTEND(p,n) MEXTEND(p,n)
 #else
-# define EXTEND(p,n)   STMT_START {                                     \
+#  ifdef STRESS_REALLOC
+#    error STRESS_REALLOC and PERL_ALT_STACKS not implemented
+#  else
+#    define EXTEND(p,n)   NOOP
+#    define MEXTEND(p,n)  NOOP
+#    define REXTEND(p,n)   STMT_START {                                 \
                          if (UNLIKELY(PL_stack_max - p < (int)(n))) {   \
                            sp = stack_grow(sp,p,(SSize_t) (n));         \
                            PERL_UNUSED_VAR(sp);                         \
                          } } STMT_END
+
 /* Same thing, but update mark register too. */
-# define MEXTEND(p,n)  STMT_START {                                     \
+#    define RMEXTEND(p,n)  STMT_START {                                 \
                          if (UNLIKELY(PL_stack_max - p < (int)(n))) {   \
                            const int markoff = mark - PL_stack_base;    \
                            sp = stack_grow(sp,p,(SSize_t) (n));         \
                            mark = PL_stack_base + markoff;              \
                            PERL_UNUSED_VAR(sp);                         \
                          } } STMT_END
-#endif
+#  endif /* STRESS_REALLOC */
+#endif /* PERL_ALT_STACKS */
 
 #define PUSHs(s)	(*++sp = (s))
 #define PUSHTARG	STMT_START { SvSETMAGIC(TARG); PUSHs(TARG); } STMT_END
@@ -307,6 +332,7 @@ Does not use C<TARG>.  See also C<XPUSHu>, C<mPUSHu> and C<PUSHu>.
 #define PUSHu(u)	STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END
 
 #define XPUSHs(s)	STMT_START { EXTEND(sp,1); *++sp = (s); } STMT_END
+#define RXPUSHs(s)	STMT_START { REXTEND(sp,1); *++sp = (s); } STMT_END
 #define XPUSHTARG	STMT_START { SvSETMAGIC(TARG); XPUSHs(TARG); } STMT_END
 #define XPUSHp(p,l)	STMT_START { sv_setpvn(TARG, (p), (l)); XPUSHTARG; } STMT_END
 #define XPUSHn(n)	STMT_START { sv_setnv(TARG, (NV)(n)); XPUSHTARG; } STMT_END
diff --git a/pp_ctl.c b/pp_ctl.c
index 0260a87..9ff0247 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1002,8 +1002,14 @@ PP(pp_mapwhile)
 	    dst = (SP += shift);
 	    PL_markstack_ptr[-1] += shift;
 	    *PL_markstack_ptr += shift;
-	    while (count--)
-		*dst-- = *src--;
+            //copy upwards not downwards
+            if(count) {
+                SV** dst1 = dst;
+                SV** src1 = src;
+                dst1 -= (count-1);
+                src1 -= (count-1);
+                memcpy(dst1, src1, sizeof(SV**)*count);
+            }
 	}
 	/* copy the new items down to the destination list */
 	dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1;
diff --git a/proto.h b/proto.h
index fb040c9..77dbf72 100644
--- a/proto.h
+++ b/proto.h
@@ -5292,6 +5292,11 @@ PERL_CALLCONV char*	Perl_my_bcopy(const char* from, char* to, I32 len)
 	assert(from); assert(to)
 
 #endif
+#if 0
+#  if defined(PERL_ALT_STACKS)
+PERL_CALLCONV int	Perl_call_runops(pTHX);
+#  endif
+#endif
 #if defined(DEBUGGING)
 PERL_CALLCONV int	Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
 			__attribute__warn_unused_result__
@@ -5497,6 +5502,9 @@ PERL_CALLCONV MEM_SIZE	Perl_malloced_size(void *p)
 #if defined(NO_MATHOMS)
 /* PERL_CALLCONV void	Perl_sv_nounlocking(pTHX_ SV *sv); */
 #endif
+#if defined(PERL_ALT_STACKS)
+PERL_CALLCONV DWORD	Perl_fix_win32stacks(LPEXCEPTION_POINTERS exceptions);
+#endif
 #if defined(PERL_ANY_COW)
 PERL_CALLCONV SV*	Perl_sv_setsv_cow(pTHX_ SV* dstr, SV* sstr)
 			__attribute__nonnull__(pTHX_2);
diff --git a/run.c b/run.c
index ff3bc93..bc23cae 100644
--- a/run.c
+++ b/run.c
@@ -48,6 +48,24 @@ Perl_runops_standard(pTHX)
     return 0;
 }
 
+#if 0
+#ifdef PERL_ALT_STACKS
+int
+Perl_call_runops(pTHX)
+{
+    __try {
+        return PL_runops(aTHX);
+    }
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+    croak_no_mem();
+}
+#endif
+#endif
+
 /*
  * Local variables:
  * c-indentation-style: bsd
diff --git a/scope.c b/scope.c
index 76e023a..6a004c6 100644
--- a/scope.c
+++ b/scope.c
@@ -56,7 +56,55 @@ Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems)
     Newx(si, 1, PERL_SI);
     si->si_stack = newAV();
     AvREAL_off(si->si_stack);
+#ifndef PERL_ALT_STACKS
     av_extend(si->si_stack, stitems > 0 ? stitems-1 : 0);
+#else
+    {
+    void *avarr;
+    void * avarr2;
+    void * toalloc;
+    Safefree(AvALLOC(si->si_stack));
+    AvALLOC(si->si_stack) = NULL;
+    AvARRAY(si->si_stack) = NULL;
+    AvMAX(si->si_stack) = SSize_t_MAX/sizeof(SV*);
+    //fprintf(stderr, "stack alloc NSI av=%x\n", si->si_stack);
+    avarr = VirtualAlloc(
+        NULL,
+        STACKMAX,
+        MEM_RESERVE,
+        PAGE_NOACCESS
+    );
+    if(!avarr) {
+        DWORD e = GetLastError();
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    //4096 (page size) should be constant or runtime lookup from Win32 API, for
+    //4096 on 32 and x64, 8K on ia64 http://blogs.msdn.com/b/oldnewthing/archive/2004/09/08/226797.aspx
+    if(! (avarr2 = VirtualAlloc(avarr,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE
+                   ))) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    (DWORD_PTR)toalloc = (DWORD_PTR)avarr+PERL_PAGESIZE;
+    if(!VirtualAlloc(toalloc,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE|PAGE_GUARD
+                   )) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+    AvALLOC(si->si_stack) = (SV**)avarr;
+    AvARRAY(si->si_stack) = (SV**)avarr;
+    }
+#endif
     AvALLOC(si->si_stack)[0] = &PL_sv_undef;
     AvFILLp(si->si_stack) = 0;
     si->si_prev = 0;
diff --git a/sv.c b/sv.c
index 13ea53c..d627c0c 100644
--- a/sv.c
+++ b/sv.c
@@ -6433,6 +6433,19 @@ Perl_sv_clear(pTHX_ SV *const orig_sv)
 		    iter_sv = sv;
 		    goto get_next_sv; /* process this new sv */
 		}
+#ifdef PERL_ALT_STACKS
+                if(!AvREAL((const AV *)av) && AvMAX((const AV *)av) == SSize_t_MAX/sizeof(SV*)) {
+                    //fprintf(stderr, "stack dealloc av=%x\n", av);
+                    if(!VirtualFree(
+                        AvALLOC(av),
+                        0,
+                        MEM_RELEASE
+                        )) {
+                        fprintf(stderr, "VF failed %u\n", GetLastError());
+                        exit(1);
+                        }
+                } else
+#endif
 		Safefree(AvALLOC(av));
 	    }
 
@@ -6777,6 +6790,8 @@ Perl_sv_free(pTHX_ SV *const sv)
 /* Private helper function for SvREFCNT_dec().
  * Called with rc set to original SvREFCNT(sv), where rc == 0 or 1 */
 
+SV * watch_sv;
+
 void
 Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
 {
@@ -6784,6 +6799,9 @@ Perl_sv_free2(pTHX_ SV *const sv, const U32 rc)
 
     PERL_ARGS_ASSERT_SV_FREE2;
 
+    if( sv == watch_sv) {
+        DebugBreak();
+    }
     if (LIKELY( rc == 1 )) {
         /* normal case */
         SvREFCNT(sv) = 0;
@@ -12683,6 +12701,48 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 		    SSize_t items = AvFILLp((const AV *)sstr) + 1;
 
 		    src_ary = AvARRAY((const AV *)sstr);
+#ifdef PERL_ALT_STACKS
+		    if(!AvREAL((const AV *)sstr) && AvMAX((const AV *)sstr) == SSize_t_MAX/sizeof(SV*)) {
+			MEMORY_BASIC_INFORMATION mbi;
+			void * avarr;
+			DWORD_PTR toalloc;
+			void * avarr2;
+			//fprintf(stderr, "stack alloc S_sv_dup_common src av=%x dst av=%x\n", sstr, dstr);
+			if(VirtualQuery(src_ary,&mbi,sizeof(mbi)) != sizeof(mbi)){
+			    DebugBreak();
+			    fprintf(stderr, "VQ failed %u\n", GetLastError());
+			    exit(1);
+			}
+			avarr = VirtualAlloc(
+			    NULL,
+			    33554432, //2^25 32 MB
+			    MEM_RESERVE,
+			    PAGE_NOACCESS
+			);
+			if(!avarr) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			if(! (avarr2 = VirtualAlloc(avarr,
+				       mbi.RegionSize,
+				       MEM_COMMIT,
+				       PAGE_READWRITE
+				       ))) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			toalloc = (DWORD_PTR) avarr + mbi.RegionSize;
+			if(!VirtualAlloc(toalloc,
+				       4096,
+				       MEM_COMMIT,
+				       PAGE_READWRITE|PAGE_GUARD
+				       )) {
+			    fprintf(stderr, "VA failed %u\n", GetLastError());
+			    exit(1);
+			}
+			dst_ary = avarr;
+		    } else
+#endif
 		    Newxz(dst_ary, AvMAX((const AV *)sstr)+1, SV*);
 		    ptr_table_store(PL_ptr_table, src_ary, dst_ary);
 		    AvARRAY(MUTABLE_AV(dstr)) = dst_ary;
@@ -12695,10 +12755,12 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
 			while (items-- > 0)
 			    *dst_ary++ = sv_dup(*src_ary++, param);
 		    }
+                /*is this really needed? This is uninit space I think
 		    items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr);
 		    while (items-- > 0) {
 			*dst_ary++ = &PL_sv_undef;
 		    }
+                */
 		}
 		else {
 		    AvARRAY(MUTABLE_AV(dstr))	= NULL;
diff --git a/t/op/threads.t b/t/op/threads.t
index 6fb2410..90314fa 100644
--- a/t/op/threads.t
+++ b/t/op/threads.t
@@ -139,7 +139,7 @@ watchdog(180, "process");
 {
     local $SIG{__WARN__} = sub {};   # Ignore any thread creation failure warnings
     my @t;
-    for (1..100) {
+    for (1..15) { #originally 100, but that caused OOM on self allocating stacks Perl on 32 bits
         my $thr = threads->create( sub { require IO });
         last if !defined($thr);      # Probably ran out of memory
         push(@t, $thr);
diff --git a/win32/Makefile b/win32/Makefile
index 4462930..ad55193 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -1,3 +1,6 @@
+!IF "$(USE_ALT_STACKS)" == "define"
+BUILDOPT	= $(BUILDOPT) -DPERL_ALT_STACKS
+!ENDIF
 #
 # Makefile to build perl on Windows using Microsoft NMAKE.
 # Supported compilers:
@@ -23,6 +26,10 @@
 INST_DRV	= c:
 INST_TOP	= $(INST_DRV)\perl521
 
+# Use OS specific Virtual Memory APIs to speed up Perl stack manipulation
+
+USE_ALT_STACKS	= define
+
 #
 # Uncomment if you want to build a 32-bit Perl using a 32-bit compiler
 # on a 64-bit version of Windows.
@@ -306,6 +313,10 @@ BUILDOPT	= $(BUILDOPT) -DPERL_IMPLICIT_CONTEXT
 BUILDOPT	= $(BUILDOPT) -DPERL_IMPLICIT_SYS
 !ENDIF
 
+!IF "$(USE_ALT_STACKS)" == "define"
+BUILDOPT	= $(BUILDOPT) -DPERL_ALT_STACKS
+!ENDIF
+
 !IF "$(PROCESSOR_ARCHITECTURE)" == ""
 PROCESSOR_ARCHITECTURE	= x86
 !ENDIF
@@ -992,10 +1003,18 @@ $(MINIDIR) :
 	if not exist "$(MINIDIR)" mkdir "$(MINIDIR)"
 
 $(MINICORE_OBJ) : $(CORE_NOCFG_H)
+!IF "$(USE_ALT_STACKS)" == "define"
+	$(CC) -c $(CFLAGS) -DPERL_EXTERNAL_GLOB -DPERL_IS_MINIPERL -DPERL_ALT_STACKS $(OBJOUT_FLAG)$@ ..\$(*F).c
+!ELSE
 	$(CC) -c $(CFLAGS) -DPERL_EXTERNAL_GLOB -DPERL_IS_MINIPERL $(OBJOUT_FLAG)$@ ..\$(*F).c
+!ENDIF
 
 $(MINIWIN32_OBJ) : $(CORE_NOCFG_H)
+!IF "$(USE_ALT_STACKS)" == "define"
+	$(CC) -c $(CFLAGS) -DPERL_IS_MINIPERL -DPERL_ALT_STACKS $(OBJOUT_FLAG)$@ $(*F).c
+!ELSE
 	$(CC) -c $(CFLAGS) -DPERL_IS_MINIPERL $(OBJOUT_FLAG)$@ $(*F).c
+!ENDIF
 
 # -DPERL_IMPLICIT_SYS needs C++ for perllib.c
 # This is the only file that depends on perlhost.h, vmem.h, and vdir.h
diff --git a/win32/perlhost.h b/win32/perlhost.h
index 265328b..a7308b9 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -1691,6 +1691,9 @@ PerlProcGetTimeOfDay(struct IPerlProc* piPerl, struct timeval *t, void *z)
 static THREAD_RET_TYPE
 win32_start_child(LPVOID arg)
 {
+#ifdef PERL_ALT_STACKS
+__try {
+#endif
     PerlInterpreter *my_perl = (PerlInterpreter*)arg;
     int status;
     HWND parent_message_hwnd;
@@ -1801,6 +1804,16 @@ restart:
 #else
     return (DWORD)status;
 #endif
+#ifdef PERL_ALT_STACKS
+}
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+croak_no_mem();
+#endif
+
 }
 #endif /* USE_ITHREADS */
 
diff --git a/win32/perllib.c b/win32/perllib.c
index 0e44a24..abb370d 100644
--- a/win32/perllib.c
+++ b/win32/perllib.c
@@ -233,6 +233,9 @@ RunPerl(int argc, char **argv, char **env)
 
     PERL_SYS_INIT(&argc,&argv);
 
+#ifdef PERL_ALT_STACKS
+__try {
+#endif
     if (!(my_perl = perl_alloc()))
 	return (1);
     perl_construct(my_perl);
@@ -277,6 +280,16 @@ RunPerl(int argc, char **argv, char **env)
     PERL_SYS_TERM();
 
     return (exitstatus);
+
+#ifdef PERL_ALT_STACKS
+}
+    __except(GetExceptionCode() == STATUS_GUARD_PAGE_VIOLATION
+             ? Perl_fix_win32stacks(GetExceptionInformation())
+             : EXCEPTION_CONTINUE_SEARCH) {
+        NOOP;
+    }
+croak_no_mem();
+#endif
 }
 
 EXTERN_C void
diff --git a/win32/win32.c b/win32/win32.c
index cd594ca..191fcc3 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4560,6 +4560,52 @@ win32_create_message_window(void)
                         0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
 }
 
+#ifdef PERL_ALT_STACKS
+DWORD
+Perl_fix_win32stacks(LPEXCEPTION_POINTERS exceptions)
+{
+    dTHX;
+    MEMORY_BASIC_INFORMATION mbi;
+    DWORD_PTR newalloc;
+    assert(exceptions->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION
+          && exceptions->ExceptionRecord->ExceptionFlags == 0);
+//needs bounds checks to make sure the STATUS_GUARD_PAGE_VIOLATION is for Perl stack and not some other c lib doing the same thing
+    /* ExceptionAddress is EIP/ * to machine code where fault happened, its not
+      interesting */
+    /* ExceptionFlags has to be zero, or the exception is not resumable, so there
+      is no point in checking it */
+    if(exceptions->ExceptionRecord->NumberParameters == 2
+       && (exceptions->ExceptionRecord->ExceptionInformation[0] == 0 /* read fault */
+       || exceptions->ExceptionRecord->ExceptionInformation[0] == 1) /* write failt */
+       && exceptions->ExceptionRecord->ExceptionInformation[1] >= (ULONG_PTR)PL_stack_base && /* fault addr >= stack bottom */
+//should this catch something beyond the alloc or let it pass through, and catch how far beyond the alloc?
+       exceptions->ExceptionRecord->ExceptionInformation[1] <= (ULONG_PTR)PL_stack_base + STACKMAX) {
+    //this is inefficient, these things should be stored somewhere in interp struct
+    if(VirtualQuery(PL_stack_base,&mbi,sizeof(mbi)) != sizeof(mbi)){
+        DebugBreak();
+        fprintf(stderr, "VQ failed %u\n", GetLastError());
+        exit(1);
+    }
+    assert(PL_stack_base == PL_stack_base && PL_stack_base == AvARRAY(PL_curstack));
+    newalloc = (DWORD_PTR)mbi.AllocationBase+(DWORD_PTR)mbi.RegionSize;
+    if(!VirtualAlloc(newalloc,
+                   PERL_PAGESIZE,
+                   MEM_COMMIT,
+                   PAGE_READWRITE|PAGE_GUARD
+                   )) {
+        DebugBreak();
+        fprintf(stderr, "VA failed %u\n", GetLastError());
+        exit(1);
+    }
+
+    return EXCEPTION_CONTINUE_EXECUTION;
+    }
+    else { /* fault address and exception isn't from Perl */
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+}
+#endif
+
 #ifdef HAVE_INTERP_INTERN
 
 static void
diff --git a/win32/win32.h b/win32/win32.h
index bfb276f..0b07b7c 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -225,6 +225,26 @@ struct utsname {
 #  define WNOHANG	1
 #endif
 
+#ifndef PERL_PAGESIZE
+#  if defined(PAGE_SIZE)
+#    define PERL_PAGESIZE PAGE_SIZE
+#  elif defined(_M_IA64) || defined(__IA64__)
+/* http://blogs.msdn.com/b/oldnewthing/archive/2004/09/08/226797.aspx */
+#    define PERL_PAGESIZE 8192
+#  elif defined(_M_IX86) || defined(_M_X64) || defined (__i386__) || defined(__x86_64__)
+#    define PERL_PAGESIZE 4096
+#  else
+#    error Unknown page size (ARM ?)
+#  endif
+#endif
+
+#ifdef PERL_ALT_STACKS
+#  define STACKMAX 0x1F00000
+#  define PERL_ALT_STACKS_EXPR(x) x
+#else
+#  define PERL_ALT_STACKS_EXPR(x)
+#endif
+
 #define PERL_GET_CONTEXT_DEFINED
 
 /* Compiler-specific stuff. */
-- 
1.7.9.msysgit.0

@p5pRT
Copy link
Author

p5pRT commented Jun 7, 2014

From @bulk88

I created a version of self allocating stacks, where EXTEND still has the normal overhead but instead of malloc mem, it uses OS VM directly. Only 3 functions in the binary are different (create the stack AV, dup it, free it and RunPerl). After taking about an hour of time to make the benchmarks below, it shows, that using a VM block instead of an malloc block is usually "slower", and in some cases faster. I wonder if what I am testing is function alignment, or is the 0x1000 alignment of OS VM causing cache associativity collisions and cache misses.


  ext extvm ext2 extvm2
  --- ----- ---- ------
arith/mixed 100 97 100 97
arith/trig 100 94 100 94
array/copy 100 95 100 96
array/foreach 100 96 100 96
array/index 100 107 100 106
array/pop 100 100 101 99
array/shift 100 98 100 98
array/sort-num 100 100 100 100
array/sort 100 99 100 99
call/0arg 100 99 99 99
call/1arg 100 101 100 101
call/2arg 100 99 100 99
call/9arg 100 106 100 107
call/empty 100 100 100 100
call/fib 100 112 102 112
call/method 100 98 100 98
call/wantarray 100 103 100 103
hash/copy 100 101 98 105
hash/each 100 103 100 104
hash/foreach-sort 100 100 100 99
hash/foreach 100 98 100 99
hash/get 100 120 99 111
hash/set 100 102 101 104
loop/for-c 100 104 100 103
loop/for-range-const 100 79 100 79
loop/for-range 100 78 100 78
loop/getline 100 98 100 98
loop/while-my 100 101 100 101
loop/while 100 89 100 89
re/const 100 101 100 101
re/w 100 102 102 100
startup/fewmod 100 96 95 89
startup/lotsofsub 100 67 101 67
startup/noprog 100 100 103 101
string/base64 100 101 100 101
string/htmlparser 100 99 100 99
string/index-const 100 110 104 111
string/index-var 100 98 100 98
string/ipol 100 102 106 103
string/tr 100 95 100 95

AVERAGE 100 99 100 98

Results saved in file​:///C|/sources/perlbench/benchres-009/index.html

C​:\sources\perlbench>


--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2014

From @tonycoz

On Mon Jun 02 22​:54​:57 2014, bulk88 wrote​:

I thought about the self allocating concept on *nix. Is an sbrk and/or
mmap region of pages, when initially allocated and NULL filled, COWed
to a single inter-process shared page of NULLs until it is written to,
making the page "dirty" and then being added to the non-shared private
pool of the process?

That would be implementation dependent.

POSIX doesn't discuss anonymous mappings. POSIX 2008 doesn't discuss brk()/sbrk() (they've been removed)

Tony

@toddr
Copy link
Member

toddr commented Feb 13, 2020

This work seems to have died without a resolution. Barring further submissions from @bulk88 (PR please!) I suggest closing this case.

@toddr toddr added Closable? We might be able to close this ticket, but we need to check with the reporter bulk88-query labels Feb 13, 2020
@xenu xenu removed the affects-5.20 label Nov 19, 2021
@xenu xenu removed the Severity Low label Dec 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bulk88-query Closable? We might be able to close this ticket, but we need to check with the reporter distro-mswin32 type-core
Projects
None yet
Development

No branches or pull requests

3 participants