develooper Front page | perl.perl5.porters | Postings from September 2012

[perl #115032] bloat problems in OP_*, XopENTRY macros, Perl_custom_op_xop and pp_sys.c

Thread Previous
From:
bulk 88
Date:
September 24, 2012 22:56
Subject:
[perl #115032] bloat problems in OP_*, XopENTRY macros, Perl_custom_op_xop and pp_sys.c
Message ID:
rt-3.6.HEAD-11172-1348552561-1596.115032-75-0@perl.org
# New Ticket Created by  bulk 88 
# Please include the string:  [perl #115032]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=115032 >


This is a bug report for perl from bulk88@hotmail.com,

generated with the help of perlbug 1.39 running under perl 5.17.5.





-----------------------------------------------------------------

[Please describe your issue here]



Most asm code came from

____________________________________________________________________

Summary of my perl5 (revision 5 version 17 subversion 5 patch blead
2012-09-24.0

5:37:11 432d4561c48cd74f3299eddc270a890908a4512e v5.17.4-47-g432d456)
configuration:

  Snapshot of: 432d4561c48cd74f3299eddc270a890908a4512e

____________________________________________________________________

under -O1 32bit VC x86 no DEBUGGING.



OP_DESC, OP_NAME, and OP_CLASS
http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l953

__________________________________________________________________

#define OP_NAME(o) ((o)->op_type == OP_CUSTOM \

                ? XopENTRY(Perl_custom_op_xop(aTHX_ o), xop_name) \

                : PL_op_name[(o)->op_type])

#define OP_DESC(o) ((o)->op_type == OP_CUSTOM \

                ? XopENTRY(Perl_custom_op_xop(aTHX_ o), xop_desc) \

                : PL_op_desc[(o)->op_type])

#define OP_CLASS(o) ((o)->op_type == OP_CUSTOM \

                 ? XopENTRY(Perl_custom_op_xop(aTHX_ o), xop_class) \

                 : (PL_opargs[(o)->op_type] & OA_CLASS_MASK))

_______________________________________________________________________

all have a redundant double call to Perl_custom_op_xop because of
XopENTRYmacro. For example from
Perl_sv_setnv

______________________________________________________________

  1677:     case SVt_PVGV:

  1678:     if (!isGV_with_GP(sv))

28090C98 81 E1 00 C0 00 00 and         ecx,0C000h

28090C9E 81 F9 00 80 00 00 cmp         ecx,8000h

28090CA4 75 7D            jne         $L51583+10h (28090D23h)

28090CA6 83 F8 09         cmp         eax,9

28090CA9 74 05            je          Perl_sv_setnv+7Ah (28090CB0h)

28090CAB 83 F8 0A         cmp         eax,0Ah

28090CAE 75 73            jne         $L51583+10h (28090D23h)

  1679:         break;

  1680:     case SVt_PVAV:

  1681:     case SVt_PVHV:

  1682:     case SVt_PVCV:

  1683:     case SVt_PVFM:

  1684:     case SVt_PVIO:

  1685:     /* diag_listed_as: Can't coerce %s to %s in %s */

  1686:     Perl_croak(aTHX_ "Can't coerce %s to number in %s",
sv_reftype(sv,0),

  1687:              OP_DESC(PL_op));

28090CB0 8B 4F 04         mov         ecx,dword ptr [edi+4]

28090CB3 33 C0            xor         eax,eax

28090CB5 66 8B 41 10      mov         ax,word ptr [ecx+10h]

28090CB9 53               push        ebx

28090CBA BA FF 01 00 00   mov         edx,1FFh

28090CBF 8B D8            mov         ebx,eax

28090CC1 66 23 DA         and         bx,dx

28090CC4 66 81 FB 6E 01   cmp         bx,16Eh

28090CC9 5B               pop         ebx

28090CCA 75 25            jne         Perl_sv_setnv+0BBh (28090CF1h)

28090CCC 51               push        ecx

28090CCD 57               push        edi

28090CCE E8 18 37 F9 FF   call        Perl_custom_op_xop (280243EBh)

28090CD3 F6 00 02         test        byte ptr [eax],2

28090CD6 59               pop         ecx

28090CD7 59               pop         ecx

28090CD8 74 10            je          Perl_sv_setnv+0B4h (28090CEAh)

28090CDA FF 77 04         push        dword ptr [edi+4]

28090CDD 57               push        edi

28090CDE E8 08 37 F9 FF   call        Perl_custom_op_xop (280243EBh)

28090CE3 8B 40 08         mov         eax,dword ptr [eax+8]

28090CE6 59               pop         ecx

28090CE7 59               pop         ecx

28090CE8 EB 10            jmp         Perl_sv_setnv+0C4h (28090CFAh)

28090CEA A1 90 55 0C 28   mov         eax,dword ptr ds:[280C5590h]

28090CEF EB 09            jmp         Perl_sv_setnv+0C4h (28090CFAh)

28090CF1 23 C2            and         eax,edx

28090CF3 8B 04 85 D8 4F 0C 28 mov         eax,dword ptr [eax*4+280C4FD8h]

28090CFA 50               push        eax

28090CFB 6A 00            push        0

28090CFD 56               push        esi

28090CFE 57               push        edi

28090CFF E8 61 C4 FF FF   call        Perl_sv_reftype (2808D165h)

28090D04 83 C4 0C         add         esp,0Ch

28090D07 50               push        eax

28090D08 68 F4 44 0D 28   push        offset string "Can't coerce %s to
number in %s" (280D44F4h)

28090D0D 57               push        edi

28090D0E E8 07 E7 01 00   call        Perl_die (280AF41Ah)

  1671:     break;

  1672:     case SVt_PV:

  1673:     case SVt_PVIV:

  1674:     sv_upgrade(sv, SVt_PVNV);

28090D13 6A 06            push        6

  1675:     break;

28090D15 EB 02            jmp         $L51583+6 (28090D19h)

  1668:     case SVt_NULL:

  1669:     case SVt_IV:

  1670:     sv_upgrade(sv, SVt_NV);

28090D17 6A 03            push        3

28090D19 56               push        esi

28090D1A 57               push        edi

28090D1B E8 A1 C5 FF FF   call        Perl_sv_upgrade (2808D2C1h)

28090D20 83 C4 0C         add         esp,0Ch

_________________________________________________________________________

macro expansion of above code

_________________________________________________________________________

    case SVt_PVGV:

        if (!

            ((((sv)->sv_flags & (0x00004000 | 0x00008000)) == 0x00008000)

             && (((svtype) ((sv)->sv_flags & 0xff)) == SVt_PVGV

                 || ((svtype) ((sv)->sv_flags & 0xff)) == SVt_PVLV)))

            break;

    case SVt_PVAV:

    case SVt_PVHV:

    case SVt_PVCV:

    case SVt_PVFM:

    case SVt_PVIO:



        Perl_croak(my_perl, "Can't coerce %s to integer in %s",
Perl_sv_reftype(my_perl, sv, 0),

                   (((my_perl->Iop))->op_type ==

                    OP_CUSTOM ? ((((Perl_custom_op_xop(my_perl,
(my_perl->Iop)))->xop_flags) & 0x02)

                                 ? (Perl_custom_op_xop(my_perl,
(my_perl->Iop)))->

                                 xop_desc : PL_op_desc[OP_CUSTOM]) :
PL_op_desc[((my_perl->Iop))->


op_type]));

    default:

        (void) 0;

    }

_______________________________________________________________________



XopENTRY macro is
http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l922

_______________________________________________________________________

 922 #define XopENTRY(xop, which) \

 923     ((XopFLAGS(xop) & XOPf_ ## which) ? (xop)->which : XOPd_ ## which)

________________________________________________________________________



All uses of XopENTRY macro, found by text search, pasted by hand,

Perl_custom_op_name

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/mathoms.c#l1157

Perl_custom_op_desc

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/mathoms.c#l1164

Perl_rpeep

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.c#l11272

XopENABLE macro, assert only

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l929

OP_* macros,

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l954

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l957

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.h#l960



Perl_custom_op_name and Perl_custom_op_desc are never called by the Perl
interp, they are exported only. All callsites of Perl_custom_op_xop are
generated from asm code found through automated disassembly, it is 100%
accurate unlike "pasted by hand" stuff in this ticket which my eyes might
have missed something. The callsites reflect a Win32 Perl build.

_______________________________________________________________

Perl_do_print+149

Perl_do_print+159

Perl_do_op_dump+6F

Perl_do_op_dump+7D

Perl_debop+4C

Perl_debop+5A

Perl_custom_op_name+8

Perl_custom_op_name+1C

Perl_custom_op_desc+8

Perl_custom_op_desc+1C

S_no_fh_allowed+17

S_no_fh_allowed+25

S_bad_type_pv+17

S_bad_type_pv+25

S_bad_type_sv+17

S_bad_type_sv+25

Perl_scalarvoid+521

Perl_scalarvoid+531

Perl_ck_cmp+85

Perl_ck_cmp+95

Perl_rpeep+AF8

Perl_rpeep+B06

Perl_op_lvalue_flags+6D5

Perl_op_lvalue_flags+6E3

Perl_op_lvalue_flags+72C

Perl_op_lvalue_flags+73A

Perl_ck_fun+225

Perl_ck_fun+235

Perl_ck_fun+7BB

Perl_ck_fun+7C9

Perl_ck_fun+86D

Perl_ck_fun+87B

Perl_ck_delete+57

Perl_ck_delete+65

Perl_ck_exists+84

Perl_ck_exists+94

Perl_ck_exists+F7

Perl_ck_exists+107

S_my_kid+F4

S_my_kid+102

S_my_kid+1E7

S_my_kid+1F5

Perl_ck_split+19F

Perl_ck_split+1AD

Perl_pp_coreargs+402

Perl_pp_coreargs+418

S_dopoptolabel+64

S_dopoptolabel+78

S_dopoptoloop+4C

S_dopoptoloop+5C

Perl_pp_syswrite+282

Perl_pp_syswrite+292

Perl_pp_ioctl+1F9

Perl_pp_ioctl+209

S_vcatpvfn_missing_argument+2E

S_vcatpvfn_missing_argument+3E

S_expect_number+69

S_expect_number+79

Perl_sv_pvn_force_flags+95

Perl_sv_pvn_force_flags+A5

Perl_sv_pvn_force_flags+1FA

Perl_sv_pvn_force_flags+20A

Perl_sv_setiv+8D

Perl_sv_setiv+9D

S_not_a_number+151

S_not_a_number+161

Perl_sv_setsv_flags+8BB

Perl_sv_setsv_flags+8CB

Perl_sv_setsv_flags+927

Perl_sv_setsv_flags+937

Perl_report_uninit+65

Perl_report_uninit+75

Perl_sv_setnv+96

Perl_sv_setnv+A6

Perl_sv_utf8_downgrade+140

Perl_sv_utf8_downgrade+150

Perl_utf8n_to_uvuni+42B

Perl_utf8n_to_uvuni+43F

Perl_utf8_length+5A

Perl_utf8_length+6A

Perl_bytes_cmp_utf8+A3

Perl_bytes_cmp_utf8+B3

Perl_bytes_cmp_utf8+124

Perl_bytes_cmp_utf8+134

Perl_check_utf8_print+166

Perl_check_utf8_print+176

Perl_to_utf8_case+63

Perl_to_utf8_case+73

Perl_to_utf8_case+D6

Perl_to_utf8_case+E6

; also an entry in perl517.dll's export table

______________________________________________________________________

Notice all call sites come in pairs that are close together. All uses of
OP_NAME, found by text search, pasted by hand.



Perl_deb_stack_all

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/deb.c#l308

Perl_do_op_dump

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/dump.c#l858

Perl_runops_debug

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/dump.c#l2140

Perl_debop

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/dump.c#l2158

Perl_do_op_xmldump

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/dump.c#l2781

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/dump.c#l3188

S_dopoptolabel

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/pp_ctl.c#l1316

S_dopoptoloop

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/pp_ctl.c#l1466

PP(pp_ioctl)

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/pp_sys.c#l2338

PP(pp_ftrread)

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/pp_sys.c#l3087

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/pp_sys.c#l3094

Perl_runops_standard

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/run.c#l41

http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/run.c#l43



There are 3 DIE macro calls taking a OP_NAME(PL_op), and 1 substitution
format string, in pp_sys.c that should be placed into a noreturn
static,something like "PERL_STATIC_INLINE_NO_RET
void S_die_op_name(pTHX_ const char * pat) __attribute__noreturn__ ;" .
There are more difficult candidates in pp_ctl.c in S_dopoptolabel
S_dopoptoloop with code sections around identical Perl_ck_warner calls but
I can't visualize the positive or negative performance impact of creating a
static for those 2 identical code chunks since ck_warner is always called
and its args are always executed. 2nd IDK if

______________________________________________________________

          if (CxTYPE(cx) == CXt_NULL)

            return -1;

______________________________________________________________

is tailcallable in the *average* C compiler since it is a conditional, not
absolute, return in the caller's frame.



My solution for OP_NAME is that Perl_custom_op_name is rehabilitated to
implement the OP_NAME macro again. All the callsites for OP_NAME are "Exiting
subroutine via %s" warning, croaks, or debugging internals data dumping to
text or macroed out 3rd party instrumentation hooks (Dtrace). No hot code
paths.



OP_CLASS macro is never used anywhere in Perl. It is used in B and
XS::APITest. PPPort does not have an implementation of it for old Perls. I
guess make it a static inline or an exported Perl_.



I will do write up on OP_DESC macro in reply to this ticket/OP soon.



Remembering vaguely from 7 hours ago, the Perl_custom_op_xop double call
problem was created in a 2010 commit. If anyone wants me to trace the
problem in detail through commit history of how the double call bug
happened tell me.



Also I'm not sure if XopENTRY_set should be fixed since its expansion is

________________________________________________________________________

#define XopENTRY_set(xop, which, to) \

    STMT_START { \

      (xop)->which = (to); \

      (xop)->xop_flags |= XOPf_ ## which; \

    } STMT_END

_________________________________________________________________________

but the only 2 uses operate on dumb data in Perl_custom_op_xop, at
http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.c#l11333and
http://perl5.git.perl.org/perl.git/blob/898c3bcab476295054cadaceb5ce68aa230a2d46:/op.c#l11338so
its fine at the moment, but maybe it won't be fine in the future. An
static inlined function in the brand new inline.h wouldn't be a bad idea,
code generation shouldn't be any different. Below is the chunk of asm in
Perl_custom_op_xop where the 2 XopENTRY_set are used. They are not a
problem in the asm code below.

_________________________________________________________________________

 11333:     XopENTRY_set(xop, xop_name, savepvn(pv, l));

28023E9D FF 75 08         push        dword ptr [my_perl]

28023EA0 50               push        eax

28023EA1 57               push        edi

28023EA2 E8 65 92 08 00   call        Perl_savepvn (280AD10Ch)

28023EA7 83 0E 01         or          dword ptr [esi],1

28023EAA 89 46 04         mov         dword ptr [esi+4],eax

 11334:     if (PL_custom_op_descs &&

 11335:         (he = hv_fetch_ent(PL_custom_op_descs, keysv, 0, 0))

 11336:     ) {

28023EAD 8B 87 24 09 00 00 mov         eax,dword ptr [edi+924h]

28023EB3 83 C4 0C         add         esp,0Ch

28023EB6 3B C3            cmp         eax,ebx

28023EB8 74 5E            je          Perl_custom_op_xop+133h (28023F18h)

28023EBA 53               push        ebx

28023EBB 53               push        ebx

28023EBC 53               push        ebx

28023EBD 53               push        ebx

28023EBE 53               push        ebx

28023EBF 53               push        ebx

28023EC0 FF 75 FC         push        dword ptr [keysv]

28023EC3 50               push        eax

28023EC4 57               push        edi

28023EC5 E8 D2 11 FF FF   call        Perl_hv_common (2801509Ch)

28023ECA 83 C4 24         add         esp,24h

28023ECD 3B C3            cmp         eax,ebx

28023ECF 74 47            je          Perl_custom_op_xop+133h (28023F18h)

 11337:         pv = SvPV(HeVAL(he), l);

28023ED1 8B 48 08         mov         ecx,dword ptr [eax+8]

28023ED4 8B 51 08         mov         edx,dword ptr [ecx+8]

28023ED7 81 E2 00 04 20 00 and         edx,200400h

28023EDD 81 FA 00 04 00 00 cmp         edx,400h

28023EE3 75 10            jne         Perl_custom_op_xop+110h (28023EF5h)

28023EE5 8B 09            mov         ecx,dword ptr [ecx]

28023EE7 8B 49 08         mov         ecx,dword ptr [ecx+8]

28023EEA 89 4D 08         mov         dword ptr [my_perl],ecx

28023EED 8B 40 08         mov         eax,dword ptr [eax+8]

28023EF0 8B 40 0C         mov         eax,dword ptr [eax+0Ch]

28023EF3 EB 10            jmp         Perl_custom_op_xop+120h (28023F05h)

28023EF5 6A 02            push        2

28023EF7 8D 45 08         lea         eax,[my_perl]

28023EFA 50               push        eax

28023EFB 51               push        ecx

28023EFC 57               push        edi

28023EFD E8 25 1C 06 00   call        Perl_sv_2pv_flags (28085B27h)

28023F02 83 C4 10         add         esp,10h

 11338:         XopENTRY_set(xop, xop_desc, savepvn(pv, l));

28023F05 FF 75 08         push        dword ptr [my_perl]

28023F08 50               push        eax

28023F09 57               push        edi

28023F0A E8 FD 91 08 00   call        Perl_savepvn (280AD10Ch)

28023F0F 83 C4 0C         add         esp,0Ch

28023F12 83 0E 02         or          dword ptr [esi],2

28023F15 89 46 08         mov         dword ptr [esi+8],eax

 11339:     }

 11340:     Perl_custom_op_register(aTHX_ o->op_ppaddr, xop);

_______________________________________________________________





[Please do not change anything below this line]

-----------------------------------------------------------------

---

Flags:

    category=core

    severity=low

---

Site configuration information for perl 5.17.5:



Configured by Owner at Mon Sep 24 02:01:27 2012.



Summary of my perl5 (revision 5 version 17 subversion 5 patch blead
2012-09-24.05:37:11 432d4561c48cd74f3299eddc270a890908a4512e
v5.17.4-47-g432d456) configuration:

  Snapshot of: 432d4561c48cd74f3299eddc270a890908a4512e

  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

    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef

    use64bitint=undef, use64bitall=undef, uselongdouble=undef

    usemymalloc=n, bincompat5005=undef

  Compiler:

    cc='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -G7 -DWIN32
-D_CONSOLE -DNO_STRICT  -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT
-DPERL_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T',

    optimize='-MD -Zi -DNDEBUG -O1 -G7',

    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
-libpath:"c:\perl517\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=perl517.lib

    gnulibc_version=''

  Dynamic Linking:

    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '

    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug
-opt:ref,icf  -libpath:"c:\perl517\lib\CORE"  -machine:x86'



Locally applied patches:





---

@INC for perl 5.17.5:

    C:/perl517/site/lib

    C:/perl517/lib

    .



---

Environment for perl 5.17.5:

    HOME (unset)

    LANG (unset)

    LANGUAGE (unset)

    LD_LIBRARY_PATH (unset)

    LOGDIR (unset)

    PATH=C:\perl517\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)

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About