1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 21:40:33 +02:00

Merge commit 'cb9d473112' into vm-check

This commit is contained in:
Andy Wingo 2009-03-17 16:41:01 +01:00
commit bb06fceef0
11 changed files with 205 additions and 178 deletions

4
NEWS
View file

@ -43,6 +43,10 @@ indicating length of the `scm_t_option' array.
** Primitive procedures (aka. "subrs") are now stored in double cells ** Primitive procedures (aka. "subrs") are now stored in double cells
This removes the subr table and simplifies the code. This removes the subr table and simplifies the code.
** Primitive procedures with more than 3 arguments (aka. "gsubrs") are
no longer implemented using the "compiled closure" mechanism. This
simplifies code and reduces both the storage and run-time overhead.
Changes in 1.8.7 (since 1.8.6) Changes in 1.8.7 (since 1.8.6)

View file

@ -21,6 +21,9 @@
:use-module (benchmark-suite lib)) :use-module (benchmark-suite lib))
(define hook1 (make-hook 1))
(define hook3 (make-hook 3))
(with-benchmark-prefix "subr invocation" (with-benchmark-prefix "subr invocation"
(benchmark "simple subr" 700000 (benchmark "simple subr" 700000
@ -34,7 +37,18 @@
;; closures" (cclos). There, when a cclo/gsubr is called, the evaluator ;; closures" (cclos). There, when a cclo/gsubr is called, the evaluator
;; goes through `SCM_APPLY ()' and conses the arguments, which is more ;; goes through `SCM_APPLY ()' and conses the arguments, which is more
;; costly than the invocation of a "simple subr". ;; costly than the invocation of a "simple subr".
(string= "foo" "bar"))) (string= "foo" "bar"))
(benchmark "generic subr with rest arg" 700000
;; 1 required argument, 0 optional arguments, 1 rest.
(run-hook hook1 1))
(benchmark "generic subr with rest arg and 3+ parameters" 700000
;; 1 required argument, 0 optional arguments, 1 rest.
;; The evaluator considers calls with 3 and more parameters as a general
;; form and always stores the arguments into a list.
(run-hook hook3 1 2 3)))
(with-benchmark-prefix "subr application" (with-benchmark-prefix "subr application"
@ -43,4 +57,10 @@
(apply 1+ '(0))) (apply 1+ '(0)))
(benchmark "generic subr" 700000 (benchmark "generic subr" 700000
(apply string= "foo" '("bar")))) (apply string= "foo" '("bar")))
(benchmark "generic subr with rest arg" 700000
(apply run-hook hook1 '(1)))
(benchmark "generic subr with rest arg and 3+ parameters" 700000
(run-hook hook3 1 2 '(3))))

View file

@ -1541,9 +1541,6 @@ AC_CONFIG_FILES([
examples/scripts/Makefile examples/scripts/Makefile
guile-config/Makefile guile-config/Makefile
lang/Makefile lang/Makefile
lang/elisp/Makefile
lang/elisp/internals/Makefile
lang/elisp/primitives/Makefile
libguile/Makefile libguile/Makefile
scripts/Makefile scripts/Makefile
srfi/Makefile srfi/Makefile

View file

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in. ## Process this file with automake to produce Makefile.in.
## ##
## Copyright (C) 2000, 2006 Free Software Foundation, Inc. ## Copyright (C) 2000, 2006, 2009 Free Software Foundation, Inc.
## ##
## This file is part of GUILE. ## This file is part of GUILE.
## ##
@ -21,4 +21,48 @@
AUTOMAKE_OPTIONS = gnu AUTOMAKE_OPTIONS = gnu
SUBDIRS = elisp # These should be installed and distributed.
elisp_sources = \
elisp/base.scm \
elisp/example.el \
elisp/interface.scm \
elisp/transform.scm \
elisp/variables.scm \
\
elisp/primitives/buffers.scm \
elisp/primitives/char-table.scm \
elisp/primitives/features.scm \
elisp/primitives/fns.scm \
elisp/primitives/format.scm \
elisp/primitives/guile.scm \
elisp/primitives/keymaps.scm \
elisp/primitives/lists.scm \
elisp/primitives/load.scm \
elisp/primitives/match.scm \
elisp/primitives/numbers.scm \
elisp/primitives/pure.scm \
elisp/primitives/read.scm \
elisp/primitives/signal.scm \
elisp/primitives/strings.scm \
elisp/primitives/symprop.scm \
elisp/primitives/syntax.scm \
elisp/primitives/system.scm \
elisp/primitives/time.scm \
\
elisp/internals/evaluation.scm \
elisp/internals/format.scm \
elisp/internals/fset.scm \
elisp/internals/lambda.scm \
elisp/internals/load.scm \
elisp/internals/null.scm \
elisp/internals/set.scm \
elisp/internals/signal.scm \
elisp/internals/time.scm \
elisp/internals/trace.scm
subpkgdatadir = $(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)/lang
nobase_subpkgdata_DATA = $(elisp_sources)
TAGS_FILES = $(nobase_subpkgdata_DATA)
EXTRA_DIST = $(elisp_sources) elisp/ChangeLog-2008

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in.
##
## Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006, 2008 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
## GUILE is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or
## (at your option) any later version.
##
## GUILE is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public
## License along with GUILE; see the file COPYING. If not, write
## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
## Floor, Boston, MA 02110-1301 USA
AUTOMAKE_OPTIONS = gnu
SUBDIRS = internals primitives
# These should be installed and distributed.
elisp_sources = \
base.scm \
example.el \
interface.scm \
transform.scm \
variables.scm
subpkgdatadir = $(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)/lang/elisp
subpkgdata_DATA = $(elisp_sources)
TAGS_FILES = $(subpkgdata_DATA)
EXTRA_DIST = $(elisp_sources) ChangeLog-2008

View file

@ -1,42 +0,0 @@
## Process this file with automake to produce Makefile.in.
##
## Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
## GUILE is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or
## (at your option) any later version.
##
## GUILE is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public
## License along with GUILE; see the file COPYING. If not, write
## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
## Floor, Boston, MA 02110-1301 USA
AUTOMAKE_OPTIONS = gnu
# These should be installed and distributed.
elisp_sources = \
evaluation.scm \
format.scm \
fset.scm \
lambda.scm \
load.scm \
null.scm \
set.scm \
signal.scm \
time.scm \
trace.scm
subpkgdatadir = $(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)/lang/elisp/internals
subpkgdata_DATA = $(elisp_sources)
TAGS_FILES = $(subpkgdata_DATA)
EXTRA_DIST = $(elisp_sources)

View file

@ -1,51 +0,0 @@
## Process this file with automake to produce Makefile.in.
##
## Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
## GUILE is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or
## (at your option) any later version.
##
## GUILE is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public
## License along with GUILE; see the file COPYING. If not, write
## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
## Floor, Boston, MA 02110-1301 USA
AUTOMAKE_OPTIONS = gnu
# These should be installed and distributed.
elisp_sources = \
buffers.scm \
char-table.scm \
features.scm \
fns.scm \
format.scm \
guile.scm \
keymaps.scm \
lists.scm \
load.scm \
match.scm \
numbers.scm \
pure.scm \
read.scm \
signal.scm \
strings.scm \
symprop.scm \
syntax.scm \
system.scm \
time.scm
subpkgdatadir = $(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)/lang/elisp/primitives
subpkgdata_DATA = $(elisp_sources)
TAGS_FILES = $(subpkgdata_DATA)
EXTRA_DIST = $(elisp_sources)

View file

@ -1140,7 +1140,7 @@ dispatch:
debug.info->a.proc = proc; debug.info->a.proc = proc;
debug.info->a.args = SCM_EOL; debug.info->a.args = SCM_EOL;
#endif #endif
RETURN (scm_gsubr_apply (scm_list_1 (proc))); RETURN (scm_i_gsubr_apply (proc, SCM_UNDEFINED));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
#ifdef DEVAL #ifdef DEVAL
@ -1259,7 +1259,7 @@ dispatch:
debug.info->a.args = scm_cons (arg1, debug.info->a.args); debug.info->a.args = scm_cons (arg1, debug.info->a.args);
debug.info->a.proc = proc; debug.info->a.proc = proc;
#endif #endif
RETURN (scm_gsubr_apply (scm_list_2 (proc, arg1))); RETURN (scm_i_gsubr_apply (proc, arg1, SCM_UNDEFINED));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
#ifdef DEVAL #ifdef DEVAL
@ -1356,15 +1356,11 @@ dispatch:
if (!SCM_SMOB_APPLICABLE_P (proc)) if (!SCM_SMOB_APPLICABLE_P (proc))
goto badfun; goto badfun;
RETURN (SCM_SMOB_APPLY_2 (proc, arg1, arg2)); RETURN (SCM_SMOB_APPLY_2 (proc, arg1, arg2));
cclon:
case scm_tc7_gsubr: case scm_tc7_gsubr:
#ifdef DEVAL #ifdef DEVAL
RETURN (scm_gsubr_apply (scm_cons (proc, debug.info->a.args))); RETURN (scm_i_gsubr_apply_list (proc, debug.info->a.args));
#else #else
RETURN (scm_gsubr_apply RETURN (scm_i_gsubr_apply (proc, arg1, arg2, SCM_UNDEFINED));
(scm_cons (proc,
scm_cons2 (arg1, arg2,
scm_ceval_args (x, env, proc)))));
#endif #endif
case scm_tcs_struct: case scm_tcs_struct:
if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC) if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
@ -1494,7 +1490,7 @@ dispatch:
RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2, RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
SCM_CDDR (debug.info->a.args))); SCM_CDDR (debug.info->a.args)));
case scm_tc7_gsubr: case scm_tc7_gsubr:
goto cclon; RETURN (scm_i_gsubr_apply_list (proc, debug.info->a.args));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
debug.info->a.proc = proc; debug.info->a.proc = proc;
@ -1557,7 +1553,15 @@ dispatch:
RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2, RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
scm_ceval_args (x, env, proc))); scm_ceval_args (x, env, proc)));
case scm_tc7_gsubr: case scm_tc7_gsubr:
goto cclon; if (scm_is_null (SCM_CDR (x)))
/* 3 arguments */
RETURN (scm_i_gsubr_apply (proc, arg1, arg2, EVALCAR (x, env),
SCM_UNDEFINED));
else
RETURN (scm_i_gsubr_apply_list (proc,
scm_cons2 (arg1, arg2,
scm_ceval_args (x, env,
proc))));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
if (!SCM_CLOSUREP (proc)) if (!SCM_CLOSUREP (proc))
@ -1876,7 +1880,7 @@ tail:
#else #else
args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args)); args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
#endif #endif
RETURN (scm_gsubr_apply (scm_cons (proc, args))); RETURN (scm_i_gsubr_apply_list (proc, args));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
#ifdef DEVAL #ifdef DEVAL

View file

@ -21,6 +21,8 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
#include "libguile/_scm.h" #include "libguile/_scm.h"
#include "libguile/procprop.h" #include "libguile/procprop.h"
#include "libguile/root.h" #include "libguile/root.h"
@ -177,18 +179,118 @@ scm_c_define_gsubr_with_generic (const char *name,
return create_gsubr_with_generic (1, name, req, opt, rst, fcn, gf); return create_gsubr_with_generic (1, name, req, opt, rst, fcn, gf);
} }
/* Apply PROC, a gsubr, to the ARGC arguments in ARGV. ARGC is expected to
SCM match the number of arguments of the underlying C function. */
scm_gsubr_apply (SCM args) static SCM
#define FUNC_NAME "scm_gsubr_apply" gsubr_apply_raw (SCM proc, unsigned int argc, const SCM *argv)
{
SCM (*fcn) ();
unsigned int type, argc_max;
type = SCM_GSUBR_TYPE (proc);
argc_max = SCM_GSUBR_REQ (type) + SCM_GSUBR_OPT (type)
+ SCM_GSUBR_REST (type);
if (SCM_UNLIKELY (argc != argc_max))
/* We expect the exact argument count. */
scm_wrong_num_args (SCM_SNAME (proc));
fcn = SCM_SUBRF (proc);
switch (argc)
{
case 0:
return (*fcn) ();
case 1:
return (*fcn) (argv[0]);
case 2:
return (*fcn) (argv[0], argv[1]);
case 3:
return (*fcn) (argv[0], argv[1], argv[2]);
case 4:
return (*fcn) (argv[0], argv[1], argv[2], argv[3]);
case 5:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
case 7:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6]);
case 8:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7]);
case 9:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7], argv[8]);
case 10:
return (*fcn) (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
argv[6], argv[7], argv[8], argv[9]);
default:
scm_misc_error ((char *) SCM_SNAME (proc),
"gsubr invocation with more than 10 arguments not implemented",
SCM_EOL);
}
return SCM_BOOL_F; /* Never reached. */
}
/* Apply PROC, a gsubr, to the given arguments. Missing optional arguments
are added, and rest arguments are turned into a list. */
SCM
scm_i_gsubr_apply (SCM proc, SCM arg, ...)
{
unsigned int type, argc, argc_max;
SCM *argv;
va_list arg_list;
type = SCM_GSUBR_TYPE (proc);
argc_max = SCM_GSUBR_REQ (type) + SCM_GSUBR_OPT (type);
argv = alloca ((argc_max + SCM_GSUBR_REST (type)) * sizeof (*argv));
va_start (arg_list, arg);
for (argc = 0;
!SCM_UNBNDP (arg) && argc < argc_max;
argc++, arg = va_arg (arg_list, SCM))
argv[argc] = arg;
if (SCM_UNLIKELY (argc < SCM_GSUBR_REQ (type)))
scm_wrong_num_args (SCM_SNAME (proc));
/* Fill in optional arguments that were not passed. */
while (argc < argc_max)
argv[argc++] = SCM_UNDEFINED;
if (SCM_GSUBR_REST (type))
{
/* Accumulate rest arguments in a list. */
SCM *rest_loc;
argv[argc_max] = SCM_EOL;
for (rest_loc = &argv[argc_max];
!SCM_UNBNDP (arg);
rest_loc = SCM_CDRLOC (*rest_loc), arg = va_arg (arg_list, SCM))
*rest_loc = scm_cons (arg, SCM_EOL);
argc = argc_max + 1;
}
va_end (arg_list);
return gsubr_apply_raw (proc, argc, argv);
}
/* Apply SELF, a gsubr, to the arguments listed in ARGS. Missing optional
arguments are added, and rest arguments are kept into a list. */
SCM
scm_i_gsubr_apply_list (SCM self, SCM args)
#define FUNC_NAME "scm_i_gsubr_apply"
{ {
SCM self = SCM_CAR (args);
SCM (*fcn)() = SCM_SUBRF (self);
SCM v[SCM_GSUBR_MAX]; SCM v[SCM_GSUBR_MAX];
unsigned int typ = SCM_GSUBR_TYPE (self); unsigned int typ = SCM_GSUBR_TYPE (self);
long i, n = SCM_GSUBR_REQ (typ) + SCM_GSUBR_OPT (typ) + SCM_GSUBR_REST (typ); long i, n = SCM_GSUBR_REQ (typ) + SCM_GSUBR_OPT (typ) + SCM_GSUBR_REST (typ);
args = SCM_CDR (args);
for (i = 0; i < SCM_GSUBR_REQ (typ); i++) { for (i = 0; i < SCM_GSUBR_REQ (typ); i++) {
if (scm_is_null (args)) if (scm_is_null (args))
scm_wrong_num_args (SCM_SNAME (self)); scm_wrong_num_args (SCM_SNAME (self));
@ -207,22 +309,8 @@ scm_gsubr_apply (SCM args)
v[i] = args; v[i] = args;
else if (!scm_is_null (args)) else if (!scm_is_null (args))
scm_wrong_num_args (SCM_SNAME (self)); scm_wrong_num_args (SCM_SNAME (self));
switch (n) {
case 2: return (*fcn)(v[0], v[1]); return gsubr_apply_raw (self, n, v);
case 3: return (*fcn)(v[0], v[1], v[2]);
case 4: return (*fcn)(v[0], v[1], v[2], v[3]);
case 5: return (*fcn)(v[0], v[1], v[2], v[3], v[4]);
case 6: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5]);
case 7: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6]);
case 8: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
case 9: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
case 10: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]);
default:
scm_misc_error ((char *) SCM_SNAME (self),
"gsubr invocation with more than 10 arguments not implemented",
SCM_EOL);
}
return SCM_BOOL_F; /* Never reached. */
} }
#undef FUNC_NAME #undef FUNC_NAME

View file

@ -48,7 +48,8 @@ SCM_API SCM scm_c_define_gsubr_with_generic (const char *name,
int req, int opt, int rst, int req, int opt, int rst,
SCM (*fcn) (), SCM *gf); SCM (*fcn) (), SCM *gf);
SCM_API SCM scm_gsubr_apply (SCM args); SCM_INTERNAL SCM scm_i_gsubr_apply (SCM proc, SCM arg, ...);
SCM_INTERNAL SCM scm_i_gsubr_apply_list (SCM proc, SCM args);
SCM_INTERNAL void scm_init_gsubr (void); SCM_INTERNAL void scm_init_gsubr (void);
#endif /* SCM_GSUBR_H */ #endif /* SCM_GSUBR_H */

View file

@ -25,11 +25,12 @@
;;; they explicitly invoke GC --- in other words, they assume that GC ;;; they explicitly invoke GC --- in other words, they assume that GC
;;; won't happen too often. ;;; won't happen too often.
(use-modules (test-suite lib) (define-module (test-guardians)
(ice-9 documentation) :use-module (test-suite lib)
(ice-9 weak-vector)) :use-module (ice-9 documentation)
:use-module (ice-9 weak-vector))
;;; ;;;
;;; miscellaneous ;;; miscellaneous
;;; ;;;