Andy Wingo <wi...@pobox.com> writes:

> Hi Andreas,
>
> I applied the first two, thanks.
>
> I am hesitant about this one for three reasons:
>
>  1) I don't want the compiler to import (rnrs arithmetic fixnums).
>     Rather, if we were to do this, I would have that module register its
>     primitives, as GOOPS does.
>
>  2) Something about this sounds wrong to me.  If fixnum? is important,
>
I don't hold the opinion that `fixnum?' per se is important; it's just
that to achieve better performance for R6RS' fixnum operations (while
still remaining within R6RS spec territory), it needs to be fast, due to
the abundance of calls to it.  If, for example, we'd make fixnum
operations VM primitives, we wouldn't need to care about `fixnum?'s
speed so much.

>  why not have it in Guile's default environment directly?
>
Well, this was what my original patch did [0], but Ludovic objected [1].

[0] http://lists.gnu.org/archive/html/guile-devel/2011-03/msg00223.html
[1] http://lists.gnu.org/archive/html/guile-devel/2011-03/msg00234.html

If you guys can reach an agreement that it should/could live in Guile's
default namespace, either named `fixnum?', or by some other name, I'll
happily re-do the patch accordingly.  My personal feeling is that having
an extension for `fixnum?' alone is clumsy, and I did this just due to
Ludovic's response.

>   Or some other non-R6RS namespace.
>
Suggestions?

>  What about, for example, `exact-integer?'?  And why for fixnums and
>  not flonums?
>
Well, the intention behind naming the files r6rs-arithmetic.{c,h} is
that similiar performance hacks for flonums could go in there as well,
but ATM I don't really care about flonum operations, so I didn't include
that in the patch.

>  3) Are there no alternatives, like exposing Guile's tags to Scheme
>     directly?  (ice-9 tags) for example.  Then we could inline tc3?,
>     tc8?, and tc16? ops.  Some other predicates would become
>     unnecessary; char? for example.  Perhaps this is a bad idea though.
>
I don't like this idea.  It sounds like exposing what is a _really_
low-level implementation detail to Scheme for not a very good reason.

Granted, `fixnum?' exposes also an implementation detail, but one that
is probably common to all non-toy implementations of Scheme, and if
hardware architectures do not change fundamentally, will probably remain
to be so.  This is also my response to Ludovic's response that "this
fixnum thing is a breach in the numerical tower": Yes, it is, but one
that can potentially provide performance gains by having the user
explicitly stating (commonly found, in some areas) invariants about the
numerical range of certain expressions.  A compiler can then leverage
this additional information to give better performance on such code.
IMO, it's a performance hack, but a potentially useful one.

> Apologies for being crabby here after you've done all this work :)  It
> could well be that something close to this is the right thing.
>
Well, I've attached my Plan-B solution.  We can come back to the
`fixnum?' VM primitive when it's clear where its corresponding Scheme
binding should go.

From: Andreas Rottmann <a.rottm...@gmx.at>
Subject: Move `define-inlinable' into the default namespace

* module/ice-9/boot-9.scm (define-inlineable): Moved here from SRFI-9.
* module/srfi/srfi-9 (define-inlinable): Removed here.

* doc/ref/api-procedures.texi (Inlinable Procedures): Add subsection
  about `define-inlinable'.

---
 doc/ref/api-procedures.texi |   27 ++++++++++++++++++++++++++-
 module/ice-9/boot-9.scm     |   36 ++++++++++++++++++++++++++++++++++++
 module/srfi/srfi-9.scm      |   32 --------------------------------
 3 files changed, 62 insertions(+), 33 deletions(-)

diff --git a/doc/ref/api-procedures.texi b/doc/ref/api-procedures.texi
index 02889c4..4b4870d 100644
--- a/doc/ref/api-procedures.texi
+++ b/doc/ref/api-procedures.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
-@c Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010
+@c Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -16,6 +16,7 @@
 * Higher-Order Functions::      Function that take or return functions.
 * Procedure Properties::        Procedure properties and meta-information.
 * Procedures with Setters::     Procedures with setters.
+* Inlinable Procedures::        Procedures that can be inlined.
 @end menu
 
 
@@ -797,6 +798,30 @@ Return the setter of @var{proc}, which must be either a procedure with
 setter or an operator struct.
 @end deffn
 
+@node Inlinable Procedures
+@subsection Inlinable Procedures
+
+You can define an ``inlinable procedure'' by using
+@code{define-inlinable} instead of @code{define}. An inlinable procedure
+behaves the same as a regular procedure, but direct calls will result in
+the procedure body being inlined into the caller.
+
+Making a procedure inlinable eliminates the overhead of the call, but at
+the same time means that the caller will not transparently use the new
+definition if the inline procedure is redefined.  Inlinable procedures
+will also not deal nicely with debugging and tracing.  Therefore, you
+should not make a procedure inlinable unless it demonstrably improves
+performance in a crucial way.
+
+In general, only small procedures should be considered for inlining, as
+making large procedures inlinable will probably result in an increase in
+code size.  Additionally, the elimination of the call overhead rarely
+matters for for large procedures.
+
+@deffn {Scheme Syntax} define-inlinable (name parameter ...) . body
+Define @var{name} as a procedure with parameters @var{parameter}s and
+body @var{body}.
+@end deffn
 
 @c Local Variables:
 @c TeX-master: "guile.texi"
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 33aa333..327e3fa 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -3497,6 +3497,42 @@ module '(ice-9 q) '(make-q q-length))}."
                          x)))))
 
 
+;;; Defining transparently inlinable procedures
+;;;
+
+(define-syntax define-inlinable
+  ;; Define a macro and a procedure such that direct calls are inlined, via
+  ;; the macro expansion, whereas references in non-call contexts refer to
+  ;; the procedure.  Inspired by the `define-integrable' macro by Dybvig et al.
+  (lambda (x)
+    ;; Use a space in the prefix to avoid potential -Wunused-toplevel
+    ;; warning
+    (define prefix (string->symbol "% "))
+    (define (make-procedure-name name)
+      (datum->syntax name
+                     (symbol-append prefix (syntax->datum name)
+                                    '-procedure)))
+
+    (syntax-case x ()
+      ((_ (name formals ...) body ...)
+       (identifier? #'name)
+       (with-syntax ((proc-name  (make-procedure-name #'name))
+                     ((args ...) (generate-temporaries #'(formals ...))))
+         #`(begin
+             (define (proc-name formals ...)
+               body ...)
+             (define-syntax name
+               (lambda (x)
+                 (syntax-case x ()
+                   ((_ args ...)
+                    #'((lambda (formals ...)
+                         body ...)
+                       args ...))
+                   (_
+                    (identifier? x)
+                    #'proc-name))))))))))
+
+
 
 (define using-readline?
   (let ((using-readline? (make-fluid)))
diff --git a/module/srfi/srfi-9.scm b/module/srfi/srfi-9.scm
index f9449a6..ad9e95d 100644
--- a/module/srfi/srfi-9.scm
+++ b/module/srfi/srfi-9.scm
@@ -64,38 +64,6 @@
 
 (cond-expand-provide (current-module) '(srfi-9))
 
-(define-syntax define-inlinable
-  ;; Define a macro and a procedure such that direct calls are inlined, via
-  ;; the macro expansion, whereas references in non-call contexts refer to
-  ;; the procedure.  Inspired by the `define-integrable' macro by Dybvig et al.
-  (lambda (x)
-    ;; Use a space in the prefix to avoid potential -Wunused-toplevel
-    ;; warning
-    (define prefix (string->symbol "% "))
-    (define (make-procedure-name name)
-      (datum->syntax name
-                     (symbol-append prefix (syntax->datum name)
-                                    '-procedure)))
-
-    (syntax-case x ()
-      ((_ (name formals ...) body ...)
-       (identifier? #'name)
-       (with-syntax ((proc-name  (make-procedure-name #'name))
-                     ((args ...) (generate-temporaries #'(formals ...))))
-         #`(begin
-             (define (proc-name formals ...)
-               body ...)
-             (define-syntax name
-               (lambda (x)
-                 (syntax-case x ()
-                   ((_ args ...)
-                    #'((lambda (formals ...)
-                         body ...)
-                       args ...))
-                   (_
-                    (identifier? x)
-                    #'proc-name))))))))))
-
 (define-syntax define-record-type
   (lambda (x)
     (define (field-identifiers field-specs)
-- 
tg: (78d1be4..) t/refactor-define-inlinable (depends on: stable-2.0)
From: Andreas Rottmann <a.rottm...@gmx.at>
Subject: Implement R6RS' `fixnum?' in a smarter way

* module/rnrs/arithmetic/fixnums.scm (fixnum?): Implemented using
  bit-twiddling, and using `define-inlinable'.

---
 module/rnrs/arithmetic/fixnums.scm |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/module/rnrs/arithmetic/fixnums.scm b/module/rnrs/arithmetic/fixnums.scm
index 03511ed..0ce2458 100644
--- a/module/rnrs/arithmetic/fixnums.scm
+++ b/module/rnrs/arithmetic/fixnums.scm
@@ -76,6 +76,7 @@
 	  fxreverse-bit-field)
   (import (only (guile) ash
 		        cons*
+			define-inlinable
 			inexact->exact
 			logand
 			logbit?
@@ -84,7 +85,8 @@
 			lognot
 			logxor
 			most-positive-fixnum 
-			most-negative-fixnum)
+			most-negative-fixnum
+			object-address)
 	  (ice-9 optargs)
 	  (rnrs base (6))
 	  (rnrs control (6))
@@ -99,12 +101,9 @@
 
   (define (greatest-fixnum) most-positive-fixnum)
   (define (least-fixnum) most-negative-fixnum)
-  
-  (define (fixnum? obj) 
-    (and (integer? obj) 
-	 (exact? obj) 
-	 (>= obj most-negative-fixnum) 
-	 (<= obj most-positive-fixnum)))
+
+  (define-inlinable (fixnum? obj)
+    (not (= 0 (logand 2 (object-address obj)))))
 
   (define-syntax assert-fixnum
     (syntax-rules ()
-- 
tg: (dfabfe2..) t/smart-fixnum-p (depends on: t/rnrs-arithmetic-benchmark t/refactor-define-inlinable)

Regards, Rotty
-- 
Andreas Rottmann -- <http://rotty.yi.org/>

Reply via email to