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

[PATCH] make sv_backoff tailcall friendly #14928

Closed
p5pRT opened this issue Sep 25, 2015 · 5 comments
Closed

[PATCH] make sv_backoff tailcall friendly #14928

p5pRT opened this issue Sep 25, 2015 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 25, 2015

Migrated from rt.perl.org#126171 (status was 'resolved')

Searchable as RT126171$

@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2015

From @bulk88

Created by @bulk88

See attached patch.

Perl Info

Flags:
           category=core
           severity=low

Site configuration information for perl 5.23.0:

Configured by Owner at Mon Jun 29 03:16:56 2015.

Summary of my perl5 (revision 5 version 23 subversion 0) configuration:
         Derived from: 63602a3fc27a417daf3c532b6a11ae6eba2a072a
         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 -GL
-DWIN32
-D_CONSOLE -DNO_STRICT  -DPERL_TEXTMODE_SCRIPTS -DPERL_IMPLICIT_CONTEXT
-DPERL_IMPLICIT_SYS -D_USE_32BIT_TIME_T',
           optimize='-O1 -MD -Zi -DNDEBUG -GL',
           cppflags='-DWIN32'
           ccversion='13.10.6030', gccversion='', gccosandvers=''
           intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234,
doublekind=3
           d_longlong=undef, longlongsize=8, d_longdbl=define, 
longdblsize=8,
longdblkind=0
           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:\perl\lib\CORE" 		-machine:x86'
           libpth=\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=perl523.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:\perl\lib\CORE" 		-machine:x86'

Locally applied patches:
           uncommitted-changes


@INC for perl 5.23.0:
           C:/perl521/srcnewb4opt/lib
           .


Environment for perl 5.23.0:
           HOME (unset)
           LANG (unset)
           LANGUAGE (unset)
           LD_LIBRARY_PATH (unset)
           LOGDIR (unset)
           PATH=C:\sperl\c\bin;C:\WINDOWS\system32;C:\Program 
Files\Microsoft
Visual Studio .NET 2003\Vc7\bin;C:\Program Files\Microsoft Visual Studio
.NET 2003\Common7\IDE;C:\WINDOWS;C:\Program Files\Git\cmd;C:\Program
Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;C:\perl\bin
           PERL_BADLANG (unset)
           PERL_JSON_BACKEND=Cpanel::JSON::XS
           PERL_YAML_BACKEND=YAML
           SHELL (unset)










@p5pRT
Copy link
Author

p5pRT commented Sep 25, 2015

From @bulk88

0001-make-sv_backoff-tailcall-friendly.patch
From 5fb6746396aaf06e315d1179cfe26d1c33f0334c Mon Sep 17 00:00:00 2001
From: Daniel Dragan <bulk88@hotmail.com>
Date: Fri, 25 Sep 2015 00:40:43 -0400
Subject: [PATCH] make sv_backoff tailcall friendly

sv_backoff has only 1.5 function calls in it, there is a memcpy of a U32 *
for alignment reasons (I wont discuss U32_ALIGNMENT_REQUIRED) inside of
SvOOK_offset, and the explicit Move()/memmove. GCC and clang often inline
memcpy/memmove when the length is a constant and is small. Sometimes
a CC might also do unaligned memory reads if OS/CPU allows it
http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130513/174807.html
so I'll assume memcpy by short constant isn't a func call for discussion.
By moving SvFLAGS modification before the one and only func call, and
changing the return type to void, there is no code to execute after the
Move func call so the CC, if it wants (OS/ABI/CPU, specifically I am
thinking about x86-64) can tailcall jump to memmove. Also var sv can be
stored in a cheaper vol reg since it is not saved around any func calls
(SvFLAGS set was moved) assuming the memcpy by short constant was inlined.

The before machine code size of Perl_sv_backoff with VC 2003 -O1 was
0x6d bytes. After size is 0x61. .text section size of perl523.dll was
after was 0xD2733 bytes long, before was 0xD2743 bytes long. VC perl does
not inline memcpys by default.

In commit a0d0e21ea6 "perl 5.000" the return 0 was added. The int ret type
is from day 1 of sv_backoff function existing/day 1 of SV *s
from commit 79072805bf "perl 5.0 alpha 2". str_backoff didn't exist AFAIK,
only str_grow would retake the memory at the start of the block. Since
sv_backoff is usually used in a "&& func()" macro (SvOOK_off), it needed a
non void ret type, a simple ", 0" in the macro fixes that. All CCs optimize
and remove "if(0)" machine instructions so the ", 0" is optimized away in
the perl binary.
---
 embed.fnc         |    2 +-
 pod/perldelta.pod |    8 +++++++-
 proto.h           |    2 +-
 sv.c              |   10 +++++++---
 sv.h              |    2 +-
 5 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index d9b43d1..db731be 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -1374,7 +1374,7 @@ Apd	|I32	|sv_true	|NULLOK SV *const sv
 sd	|void	|sv_add_arena	|NN char *const ptr|const U32 size \
 				|const U32 flags
 #endif
-Apdn	|int	|sv_backoff	|NN SV *const sv
+Apdn	|void	|sv_backoff	|NN SV *const sv
 Apd	|SV*	|sv_bless	|NN SV *const sv|NN HV *const stash
 #if defined(PERL_DEBUG_READONLY_COW)
 p	|void	|sv_buf_to_ro	|NN SV *sv
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index db9e601..7c6b5e7 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -323,7 +323,13 @@ well.
 
 =item *
 
-XXX
+L<perlapi/sv_backoff> had its return type changed fron C<int> to C<void>.  It
+previously has always returned C<0> since 5.000 stable but that was
+undocumented.  Although C<sv_backoff> is marked as public API, XS code is not
+expected to be impacted since the proper API call would be through public API
+C<sv_setsv(sv, &PL_sv_undef)>, or quasi-public C<SvOOK_off>, or non-public
+C<SvOK_off> calls, and the return value of C<sv_backoff> was previously a
+meaningless constant that can be rewritten as C<(sv_backoff(sv),0)>.
 
 =back
 
diff --git a/proto.h b/proto.h
index 6d49f47..fdc509c 100644
--- a/proto.h
+++ b/proto.h
@@ -2900,7 +2900,7 @@ PERL_CALLCONV char*	Perl_sv_2pvutf8(pTHX_ SV *sv, STRLEN *const lp);
 PERL_CALLCONV UV	Perl_sv_2uv_flags(pTHX_ SV *const sv, const I32 flags);
 #define PERL_ARGS_ASSERT_SV_2UV_FLAGS	\
 	assert(sv)
-PERL_CALLCONV int	Perl_sv_backoff(SV *const sv);
+PERL_CALLCONV void	Perl_sv_backoff(SV *const sv);
 #define PERL_ARGS_ASSERT_SV_BACKOFF	\
 	assert(sv)
 PERL_CALLCONV SV*	Perl_sv_bless(pTHX_ SV *const sv, HV *const stash);
diff --git a/sv.c b/sv.c
index dc2ba8b..d7d6dee 100644
--- a/sv.c
+++ b/sv.c
@@ -1525,7 +1525,11 @@ wrapper instead.
 =cut
 */
 
-int
+/* prior to 5.000 stable, this function returned the new OOK-less SvFLAGS
+   prior to 5.23.4 this function always returned 0
+*/
+
+void
 Perl_sv_backoff(SV *const sv)
 {
     STRLEN delta;
@@ -1541,9 +1545,9 @@ Perl_sv_backoff(SV *const sv)
     
     SvLEN_set(sv, SvLEN(sv) + delta);
     SvPV_set(sv, SvPVX(sv) - delta);
-    Move(s, SvPVX(sv), SvCUR(sv)+1, char);
     SvFLAGS(sv) &= ~SVf_OOK;
-    return 0;
+    Move(s, SvPVX(sv), SvCUR(sv)+1, char);
+    return;
 }
 
 /*
diff --git a/sv.h b/sv.h
index 331b823..9cb9cf6 100644
--- a/sv.h
+++ b/sv.h
@@ -949,7 +949,7 @@ in gv.h: */
 
 #define SvOOK(sv)		(SvFLAGS(sv) & SVf_OOK)
 #define SvOOK_on(sv)		(SvFLAGS(sv) |= SVf_OOK)
-#define SvOOK_off(sv)		((void)(SvOOK(sv) && sv_backoff(sv)))
+#define SvOOK_off(sv)		((void)(SvOOK(sv) && (sv_backoff(sv),0)))
 
 #define SvFAKE(sv)		(SvFLAGS(sv) & SVf_FAKE)
 #define SvFAKE_on(sv)		(SvFLAGS(sv) |= SVf_FAKE)
-- 
1.7.9.msysgit.0

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2015

From @iabyn

On Thu, Sep 24, 2015 at 09​:42​:04PM -0700, bulk88 wrote​:

See attached patch.

Thanks, applied as fa7a1e4.

I took the liberty of adding a short summary paragraph at the beginning of
the commit message, since it wasn't apparent, without reading a big body of
text, that the signature of the function was being changed too​:

  Reorder the body of Perl_sv_backoff slightly to make it more tail-call
  friendly, and change its signature from returning an int (always 0) to
  void.
 
  sv_backoff has only 1.5 function calls in it, there is a memcpy of a U32 *
  ....

--
This email is confidential, and now that you have read it you are legally
obliged to shoot yourself. Or shoot a lawyer, if you prefer. If you have
received this email in error, place it in its original wrapping and return
for a full refund. By opening this email, you accept that Elvis lives.

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2015

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

@p5pRT p5pRT closed this as completed Oct 8, 2015
@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2015

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant