diff --git a/libguile/ChangeLog b/libguile/ChangeLog index ae7a48a4b..8b7e72ce2 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,16 @@ +2007-12-08 Ludovic Courtès + + * __scm.h (SCM_EXPECT, SCM_LIKELY, SCM_UNLIKELY): New macros. + (SCM_ASSERT, SCM_ASSERT_TYPE, SCM_ASRTGO, SCM_GASSERT0, + SCM_GASSERT1, SCM_GASSERT2, SCM_GASSERTn): Use them. + * eval.c (ASSERT_SYNTAX, ASSERT_SYNTAX_2): Likewise. + (CEVAL): Use branch prediction hints for syntax errors, wrong + number of arguments and similar. + * numbers.c (scm_sum): Use `SCM_LIKELY' for the sum of two + immediate numbers. + (scm_difference, scm_product, scm_i_divide): Likewise. + * validate.h (SCM_ASSERT_RANGE): Use `SCM_UNLIKELY'. + 2007-12-04 Ludovic Courtès * ports.c (scm_c_read): Validate PORT as an open input port. diff --git a/libguile/__scm.h b/libguile/__scm.h index fc581631a..c06190481 100644 --- a/libguile/__scm.h +++ b/libguile/__scm.h @@ -3,7 +3,7 @@ #ifndef SCM___SCM_H #define SCM___SCM_H -/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006, 2007 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -109,6 +109,20 @@ #endif +/* The SCM_EXPECT macros provide branch prediction hints to the compiler. To + * use only in places where the result of the expression under "normal" + * circumstances is known. */ +#if defined(__GNUC__) && (__GNUC__ >= 3) +# define SCM_EXPECT __builtin_expect +#else +# define SCM_EXPECT(_expr, _value) (_expr) +#endif + +#define SCM_LIKELY(_expr) SCM_EXPECT ((_expr), 1) +#define SCM_UNLIKELY(_expr) SCM_EXPECT ((_expr), 0) + + + /* {Supported Options} * * These may be defined or undefined. @@ -500,14 +514,14 @@ do { \ #define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg) #define SCM_ASRTGO(_cond, _label) #else -#define SCM_ASSERT(_cond, _arg, _pos, _subr) \ - do { if (!(_cond)) \ +#define SCM_ASSERT(_cond, _arg, _pos, _subr) \ + do { if (SCM_UNLIKELY (!(_cond))) \ scm_wrong_type_arg (_subr, _pos, _arg); } while (0) -#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg) \ - do { if (!(_cond)) \ +#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg) \ + do { if (SCM_UNLIKELY (!(_cond))) \ scm_wrong_type_arg_msg(_subr, _pos, _arg, _msg); } while (0) -#define SCM_ASRTGO(_cond, _label) \ - do { if (!(_cond)) \ +#define SCM_ASRTGO(_cond, _label) \ + do { if (SCM_UNLIKELY (!(_cond))) \ goto _label; } while (0) #endif @@ -526,8 +540,9 @@ SCM_API SCM scm_call_generic_0 (SCM gf); return (SCM_UNPACK (gf) \ ? scm_call_generic_0 ((gf)) \ : (scm_error_num_args_subr ((subr)), SCM_UNSPECIFIED)) -#define SCM_GASSERT0(cond, gf, subr) \ - if (!(cond)) SCM_WTA_DISPATCH_0((gf), (subr)) +#define SCM_GASSERT0(cond, gf, subr) \ + if (SCM_UNLIKELY(!(cond))) \ + SCM_WTA_DISPATCH_0((gf), (subr)) SCM_API SCM scm_call_generic_1 (SCM gf, SCM a1); @@ -535,8 +550,9 @@ SCM_API SCM scm_call_generic_1 (SCM gf, SCM a1); return (SCM_UNPACK (gf) \ ? scm_call_generic_1 ((gf), (a1)) \ : (scm_wrong_type_arg ((subr), (pos), (a1)), SCM_UNSPECIFIED)) -#define SCM_GASSERT1(cond, gf, a1, pos, subr) \ - if (!(cond)) SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr)) +#define SCM_GASSERT1(cond, gf, a1, pos, subr) \ + if (SCM_UNLIKELY (!(cond))) \ + SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr)) SCM_API SCM scm_call_generic_2 (SCM gf, SCM a1, SCM a2); @@ -546,8 +562,9 @@ SCM_API SCM scm_call_generic_2 (SCM gf, SCM a1, SCM a2); : (scm_wrong_type_arg ((subr), (pos), \ (pos) == SCM_ARG1 ? (a1) : (a2)), \ SCM_UNSPECIFIED)) -#define SCM_GASSERT2(cond, gf, a1, a2, pos, subr) \ - if (!(cond)) SCM_WTA_DISPATCH_2((gf), (a1), (a2), (pos), (subr)) +#define SCM_GASSERT2(cond, gf, a1, a2, pos, subr) \ + if (SCM_UNLIKELY (!(cond))) \ + SCM_WTA_DISPATCH_2((gf), (a1), (a2), (pos), (subr)) SCM_API SCM scm_apply_generic (SCM gf, SCM args); @@ -558,8 +575,9 @@ SCM_API SCM scm_apply_generic (SCM gf, SCM args); scm_list_ref ((args), \ scm_from_int ((pos) - 1))), \ SCM_UNSPECIFIED)) -#define SCM_GASSERTn(cond, gf, args, pos, subr) \ - if (!(cond)) SCM_WTA_DISPATCH_n((gf), (args), (pos), (subr)) +#define SCM_GASSERTn(cond, gf, args, pos, subr) \ + if (SCM_UNLIKELY (!(cond))) \ + SCM_WTA_DISPATCH_n((gf), (args), (pos), (subr)) #ifndef SCM_MAGIC_SNARFER /* Let these macros pass through if diff --git a/libguile/eval.c b/libguile/eval.c index d0dbadaea..3c1193a50 100644 --- a/libguile/eval.c +++ b/libguile/eval.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006 +/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007 * Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or @@ -319,10 +319,12 @@ syntax_error (const char* const msg, const SCM form, const SCM expr) /* Shortcut macros to simplify syntax error handling. */ -#define ASSERT_SYNTAX(cond, message, form) \ - { if (!(cond)) syntax_error (message, form, SCM_UNDEFINED); } -#define ASSERT_SYNTAX_2(cond, message, form, expr) \ - { if (!(cond)) syntax_error (message, form, expr); } +#define ASSERT_SYNTAX(cond, message, form) \ + { if (SCM_UNLIKELY (!(cond))) \ + syntax_error (message, form, SCM_UNDEFINED); } +#define ASSERT_SYNTAX_2(cond, message, form, expr) \ + { if (SCM_UNLIKELY (!(cond))) \ + syntax_error (message, form, expr); } @@ -3717,7 +3719,7 @@ dispatch: #ifdef DEVAL debug.info->a.args = arg1; #endif - if (scm_badargsp (formals, arg1)) + if (SCM_UNLIKELY (scm_badargsp (formals, arg1))) scm_wrong_num_args (proc); ENTER_APPLY; /* Copy argument list */ @@ -4161,7 +4163,7 @@ dispatch: case scm_tcs_closures: { const SCM formals = SCM_CLOSURE_FORMALS (proc); - if (scm_is_pair (formals)) + if (SCM_UNLIKELY (scm_is_pair (formals))) goto wrongnumargs; x = SCM_CLOSURE_BODY (proc); env = SCM_EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc)); @@ -4205,7 +4207,7 @@ dispatch: /* must handle macros by here */ x = SCM_CDR (x); - if (scm_is_pair (x)) + if (SCM_LIKELY (scm_is_pair (x))) arg1 = EVALCAR (x, env); else scm_wrong_num_args (proc); @@ -4284,8 +4286,9 @@ dispatch: { /* clos1: */ const SCM formals = SCM_CLOSURE_FORMALS (proc); - if (scm_is_null (formals) - || (scm_is_pair (formals) && scm_is_pair (SCM_CDR (formals)))) + if (SCM_UNLIKELY (scm_is_null (formals) + || (scm_is_pair (formals) && + scm_is_pair (SCM_CDR (formals))))) goto wrongnumargs; x = SCM_CLOSURE_BODY (proc); #ifdef DEVAL @@ -4334,7 +4337,7 @@ dispatch: goto badfun; } } - if (scm_is_pair (x)) + if (SCM_LIKELY (scm_is_pair (x))) arg2 = EVALCAR (x, env); else scm_wrong_num_args (proc); @@ -4438,11 +4441,12 @@ dispatch: { /* clos2: */ const SCM formals = SCM_CLOSURE_FORMALS (proc); - if (scm_is_null (formals) - || (scm_is_pair (formals) - && (scm_is_null (SCM_CDR (formals)) - || (scm_is_pair (SCM_CDR (formals)) - && scm_is_pair (SCM_CDDR (formals)))))) + if (SCM_UNLIKELY + (scm_is_null (formals) + || (scm_is_pair (formals) + && (scm_is_null (SCM_CDR (formals)) + || (scm_is_pair (SCM_CDR (formals)) + && scm_is_pair (SCM_CDDR (formals))))))) goto wrongnumargs; #ifdef DEVAL env = SCM_EXTEND_ENV (formals, @@ -4458,7 +4462,7 @@ dispatch: } } } - if (!scm_is_pair (x)) + if (SCM_UNLIKELY (!scm_is_pair (x))) scm_wrong_num_args (proc); #ifdef DEVAL debug.info->a.args = scm_cons2 (arg1, arg2, @@ -4472,7 +4476,7 @@ dispatch: { /* have 3 or more arguments */ #ifdef DEVAL case scm_tc7_subr_3: - if (!scm_is_null (SCM_CDR (x))) + if (SCM_UNLIKELY (!scm_is_null (SCM_CDR (x)))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) (arg1, arg2, @@ -4536,7 +4540,7 @@ dispatch: } #else /* DEVAL */ case scm_tc7_subr_3: - if (!scm_is_null (SCM_CDR (x))) + if (SCM_UNLIKELY (!scm_is_null (SCM_CDR (x)))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) (arg1, arg2, EVALCAR (x, env))); @@ -4859,37 +4863,37 @@ tail: switch (SCM_TYP7 (proc)) { case scm_tc7_subr_2o: - if (SCM_UNBNDP (arg1)) + if (SCM_UNLIKELY (SCM_UNBNDP (arg1))) scm_wrong_num_args (proc); if (scm_is_null (args)) args = SCM_UNDEFINED; else { - if (! scm_is_null (SCM_CDR (args))) + if (SCM_UNLIKELY (!scm_is_null (SCM_CDR (args)))) scm_wrong_num_args (proc); args = SCM_CAR (args); } RETURN (SCM_SUBRF (proc) (arg1, args)); case scm_tc7_subr_2: - if (scm_is_null (args) || !scm_is_null (SCM_CDR (args))) + if (SCM_UNLIKELY (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))) scm_wrong_num_args (proc); args = SCM_CAR (args); RETURN (SCM_SUBRF (proc) (arg1, args)); case scm_tc7_subr_0: - if (!SCM_UNBNDP (arg1)) + if (SCM_UNLIKELY (!SCM_UNBNDP (arg1))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) ()); case scm_tc7_subr_1: - if (SCM_UNBNDP (arg1)) + if (SCM_UNLIKELY (SCM_UNBNDP (arg1))) scm_wrong_num_args (proc); case scm_tc7_subr_1o: - if (!scm_is_null (args)) + if (SCM_UNLIKELY (!scm_is_null (args))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) (arg1)); case scm_tc7_dsubr: - if (SCM_UNBNDP (arg1) || !scm_is_null (args)) + if (SCM_UNLIKELY (SCM_UNBNDP (arg1) || !scm_is_null (args))) scm_wrong_num_args (proc); if (SCM_I_INUMP (arg1)) { @@ -4910,13 +4914,13 @@ tail: SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1, SCM_ARG1, scm_i_symbol_chars (SCM_SNAME (proc))); case scm_tc7_cxr: - if (SCM_UNBNDP (arg1) || !scm_is_null (args)) + if (SCM_UNLIKELY (SCM_UNBNDP (arg1) || !scm_is_null (args))) scm_wrong_num_args (proc); RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc))); case scm_tc7_subr_3: - if (scm_is_null (args) - || scm_is_null (SCM_CDR (args)) - || !scm_is_null (SCM_CDDR (args))) + if (SCM_UNLIKELY (scm_is_null (args) + || scm_is_null (SCM_CDR (args)) + || !scm_is_null (SCM_CDDR (args)))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CADR (args))); @@ -4927,7 +4931,7 @@ tail: RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args))); #endif case scm_tc7_lsubr_2: - if (!scm_is_pair (args)) + if (SCM_UNLIKELY (!scm_is_pair (args))) scm_wrong_num_args (proc); else RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CDR (args))); @@ -4959,7 +4963,7 @@ tail: #else arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args)); #endif - if (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1)) + if (SCM_UNLIKELY (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1))) scm_wrong_num_args (proc); /* Copy argument list */ diff --git a/libguile/numbers.c b/libguile/numbers.c index 97b766699..6aeaee1ac 100644 --- a/libguile/numbers.c +++ b/libguile/numbers.c @@ -3950,16 +3950,16 @@ SCM_GPROC1 (s_sum, "+", scm_tc7_asubr, scm_sum, g_sum); SCM scm_sum (SCM x, SCM y) { - if (SCM_UNBNDP (y)) + if (SCM_UNLIKELY (SCM_UNBNDP (y))) { if (SCM_NUMBERP (x)) return x; if (SCM_UNBNDP (x)) return SCM_INUM0; SCM_WTA_DISPATCH_1 (g_sum, x, SCM_ARG1, s_sum); } - if (SCM_I_INUMP (x)) + if (SCM_LIKELY (SCM_I_INUMP (x))) { - if (SCM_I_INUMP (y)) + if (SCM_LIKELY (SCM_I_INUMP (y))) { long xx = SCM_I_INUM (x); long yy = SCM_I_INUM (y); @@ -4144,7 +4144,7 @@ SCM_GPROC1 (s_difference, "-", scm_tc7_asubr, scm_difference, g_difference); SCM scm_difference (SCM x, SCM y) { - if (SCM_UNBNDP (y)) + if (SCM_UNLIKELY (SCM_UNBNDP (y))) { if (SCM_UNBNDP (x)) SCM_WTA_DISPATCH_0 (g_difference, s_difference); @@ -4173,9 +4173,9 @@ scm_difference (SCM x, SCM y) SCM_WTA_DISPATCH_1 (g_difference, x, SCM_ARG1, s_difference); } - if (SCM_I_INUMP (x)) + if (SCM_LIKELY (SCM_I_INUMP (x))) { - if (SCM_I_INUMP (y)) + if (SCM_LIKELY (SCM_I_INUMP (y))) { long int xx = SCM_I_INUM (x); long int yy = SCM_I_INUM (y); @@ -4388,7 +4388,7 @@ SCM_GPROC1 (s_product, "*", scm_tc7_asubr, scm_product, g_product); SCM scm_product (SCM x, SCM y) { - if (SCM_UNBNDP (y)) + if (SCM_UNLIKELY (SCM_UNBNDP (y))) { if (SCM_UNBNDP (x)) return SCM_I_MAKINUM (1L); @@ -4398,7 +4398,7 @@ scm_product (SCM x, SCM y) SCM_WTA_DISPATCH_1 (g_product, x, SCM_ARG1, s_product); } - if (SCM_I_INUMP (x)) + if (SCM_LIKELY (SCM_I_INUMP (x))) { long xx; @@ -4411,7 +4411,7 @@ scm_product (SCM x, SCM y) case 1: return y; break; } - if (SCM_I_INUMP (y)) + if (SCM_LIKELY (SCM_I_INUMP (y))) { long yy = SCM_I_INUM (y); long kk = xx * yy; @@ -4611,7 +4611,7 @@ scm_i_divide (SCM x, SCM y, int inexact) { double a; - if (SCM_UNBNDP (y)) + if (SCM_UNLIKELY (SCM_UNBNDP (y))) { if (SCM_UNBNDP (x)) SCM_WTA_DISPATCH_0 (g_divide, s_divide); @@ -4671,10 +4671,10 @@ scm_i_divide (SCM x, SCM y, int inexact) SCM_WTA_DISPATCH_1 (g_divide, x, SCM_ARG1, s_divide); } - if (SCM_I_INUMP (x)) + if (SCM_LIKELY (SCM_I_INUMP (x))) { long xx = SCM_I_INUM (x); - if (SCM_I_INUMP (y)) + if (SCM_LIKELY (SCM_I_INUMP (y))) { long yy = SCM_I_INUM (y); if (yy == 0) diff --git a/libguile/validate.h b/libguile/validate.h index e23e83ad8..365db3693 100644 --- a/libguile/validate.h +++ b/libguile/validate.h @@ -3,7 +3,7 @@ #ifndef SCM_VALIDATE_H #define SCM_VALIDATE_H -/* Copyright (C) 1999,2000,2001, 2002, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1999,2000,2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -99,8 +99,10 @@ #define SCM_OUT_OF_RANGE(pos, arg) \ do { scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); } while (0) -#define SCM_ASSERT_RANGE(pos, arg, f) \ - do { if (!(f)) scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); } while (0) +#define SCM_ASSERT_RANGE(pos, arg, f) \ + do { if (SCM_UNLIKELY (!(f))) \ + scm_out_of_range_pos (FUNC_NAME, arg, scm_from_int (pos)); } \ + while (0) #define SCM_MUST_MALLOC_TYPE(type) \ ((type *) scm_must_malloc (sizeof (type), FUNC_NAME))