diff --git a/CHANGES.current b/CHANGES.current index 34300d43e..140ada03f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,41 @@ Version 1.3.28 (unreleased). =========================== +12/08/2005: mmatus + + - Add the -fastdispatch option (fastdispatch feature). This + enable the "fast dispatch" mechanism for overloaded + methods provided by Salvador Fandi~no Garc'ia (#930586). + + The resulting code is smaller and faster since less type + checking are performed. However, the error messages you + get when the overloading is not resolved could be + different from what the traditional method returns. + + With the old method you always get an error such as + + "No matching function for overloaded ..." + + with the new method you can also get errors such as + + "Type error in argument 1 of type ..." + + See bug report #930586 for more details. + + So, we let to the user the option to enable this + optimization. + + You use this new mechanism as + + swig -fastdispatch + + or using the feature form + + %feature("fastdispatch") method; + or + %fastdispatch method; + + 12/06/2005: mmatus - Several memory and speed improvements, specially for @@ -12,7 +47,7 @@ Version 1.3.28 (unreleased). pcs/architectures. - - add option "cpperraswarn/nocpperraswarn" to force the swig + - add options "cpperraswarn/nocpperraswarn" to force the swig preprocessor to treat the #error directive as a #warning. the default behavior is cpperraswarn, so, swig doesn't @@ -45,22 +80,27 @@ Version 1.3.28 (unreleased). %module("threads"=1) - 2.- Equivalent to that, is the following swig option + 2.- Equivalent to that, is the new '-threads' swig option swig -threads -python ... - ie, swig enables thread support for the module. - 3.- You can partially disable thread support for a given method using: %feature("nothread") method; + or + %nothread method; also, you can disable sections of the thread support, for example %feature("nothreadblock") method; + or + %nothreadblock method; + %feature("nothreadallow") method; + or + %nothreadallow method; the first disables the C++/python thread protection, and the second disables the python/C++ thread protection. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index e878a6c55..21eaa65dd 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -189,6 +189,7 @@ CPP_TEST_CASES += \ overload_simple \ overload_subtype \ overload_template \ + overload_template_fast \ pointer_reference \ primitive_ref \ private_assign \ diff --git a/Examples/test-suite/overload_template_fast.i b/Examples/test-suite/overload_template_fast.i new file mode 100644 index 000000000..83d5accaf --- /dev/null +++ b/Examples/test-suite/overload_template_fast.i @@ -0,0 +1,5 @@ +%module overload_template_fast + +%fastdispatch; + +%include overload_template.i diff --git a/Examples/test-suite/python/overload_template_fast_runme.py b/Examples/test-suite/python/overload_template_fast_runme.py new file mode 100644 index 000000000..ed1b7fa1d --- /dev/null +++ b/Examples/test-suite/python/overload_template_fast_runme.py @@ -0,0 +1,145 @@ +from overload_template import * +f = foo() + +a = max(3,4) +b = max(3.4,5.2) + +# mix 1 +if (mix1("hi") != 101): + raise RuntimeError, ("mix1(const char*)") + +if (mix1(1.0, 1.0) != 102): + raise RuntimeError, ("mix1(double, const double &)") + +if (mix1(1.0) != 103): + raise RuntimeError, ("mix1(double)") + +# mix 2 +if (mix2("hi") != 101): + raise RuntimeError, ("mix2(const char*)") + +if (mix2(1.0, 1.0) != 102): + raise RuntimeError, ("mix2(double, const double &)") + +if (mix2(1.0) != 103): + raise RuntimeError, ("mix2(double)") + +# mix 3 +if (mix3("hi") != 101): + raise RuntimeError, ("mix3(const char*)") + +if (mix3(1.0, 1.0) != 102): + raise RuntimeError, ("mix3(double, const double &)") + +if (mix3(1.0) != 103): + raise RuntimeError, ("mix3(double)") + +# Combination 1 +if (overtparams1(100) != 10): + raise RuntimeError, ("overtparams1(int)") + +if (overtparams1(100.0, 100) != 20): + raise RuntimeError, ("overtparams1(double, int)") + +# Combination 2 +if (overtparams2(100.0, 100) != 40): + raise RuntimeError, ("overtparams2(double, int)") + +# Combination 3 +if (overloaded() != 60): + raise RuntimeError, ("overloaded()") + +if (overloaded(100.0, 100) != 70): + raise RuntimeError, ("overloaded(double, int)") + +# Combination 4 +if (overloadedagain("hello") != 80): + raise RuntimeError, ("overloadedagain(const char *)") + +if (overloadedagain() != 90): + raise RuntimeError, ("overloadedagain(double)") + +# specializations +if (specialization(10) != 202): + raise RuntimeError, ("specialization(int)") + +if (specialization(10.0) != 203): + raise RuntimeError, ("specialization(double)") + +if (specialization(10, 10) != 204): + raise RuntimeError, ("specialization(int, int)") + +if (specialization(10.0, 10.0) != 205): + raise RuntimeError, ("specialization(double, double)") + +if (specialization("hi", "hi") != 201): + raise RuntimeError, ("specialization(const char *, const char *)") + + +# simple specialization +xyz() +xyz_int() +xyz_double() + +# a bit of everything +if (overload("hi") != 0): + raise RuntimeError, ("overload()") + +if (overload(1) != 10): + raise RuntimeError, ("overload(int t)") + +if (overload(1, 1) != 20): + raise RuntimeError, ("overload(int t, const int &)") + +if (overload(1, "hello") != 30): + raise RuntimeError, ("overload(int t, const char *)") + +k = Klass() +if (overload(k) != 10): + raise RuntimeError, ("overload(Klass t)") + +if (overload(k, k) != 20): + raise RuntimeError, ("overload(Klass t, const Klass &)") + +if (overload(k, "hello") != 30): + raise RuntimeError, ("overload(Klass t, const char *)") + +if (overload(10.0, "hi") != 40): + raise RuntimeError, ("overload(double t, const char *)") + +if (overload() != 50): + raise RuntimeError, ("overload(const char *)") + + +# everything put in a namespace +if (nsoverload("hi") != 1000): + raise RuntimeError, ("nsoverload()") + +if (nsoverload(1) != 1010): + raise RuntimeError, ("nsoverload(int t)") + +if (nsoverload(1, 1) != 1020): + raise RuntimeError, ("nsoverload(int t, const int &)") + +if (nsoverload(1, "hello") != 1030): + raise RuntimeError, ("nsoverload(int t, const char *)") + +if (nsoverload(k) != 1010): + raise RuntimeError, ("nsoverload(Klass t)") + +if (nsoverload(k, k) != 1020): + raise RuntimeError, ("nsoverload(Klass t, const Klass &)") + +if (nsoverload(k, "hello") != 1030): + raise RuntimeError, ("nsoverload(Klass t, const char *)") + +if (nsoverload(10.0, "hi") != 1040): + raise RuntimeError, ("nsoverload(double t, const char *)") + +if (nsoverload() != 1050): + raise RuntimeError, ("nsoverload(const char *)") + + +A.foo(1) +b = B() +b.foo(1) diff --git a/Lib/swig.swg b/Lib/swig.swg index 03a7036cf..37202d034 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -92,6 +92,11 @@ #define %nocallback %feature("callback","0") #define %clearcallback %feature("callback","") +/* the %fastdispatch directive */ +#define %fastdispatch %feature("fastdispatch") +#define %nofastdispatch %feature("fastdispatch","0") +#define %clearfastdispatch %feature("fastdispatch","") + /* Common features */ diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 1e617d4bf..bb288ff5a 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -59,7 +59,8 @@ static const char *usage1 = (const char*)"\ -features directors,autodoc=1 \n\ if not explicit value is given to the feature, a '1' is used \n\ -fvirtual - Compile in virtual elimination mode\n\ - -fdispatch - Use fast dispatch mode, which produces faster overload dispatcher code\n\ + -fastdispatch - Enable fast dispatch mode, which produces faster overload dispatcher code\n\ + -nofastdispatch - Disable fast dispatch mode (default)\n\ -Fstandard - Display error/warning messages in commonly used format\n\ -Fmicrosoft - Display error/warning messages in Microsoft format\n\ -help - This output\n\ @@ -389,9 +390,12 @@ void SWIG_getoptions(int argc, char *argv[]) } else if (strcmp(argv[i],"-fvirtual") == 0) { Wrapper_virtual_elimination_mode_set(1); Swig_mark_arg(i); - } else if (strcmp(argv[i],"-fdispatch") == 0) { + } else if (strcmp(argv[i],"-fastdispatch") == 0) { Wrapper_fast_dispatch_mode_set(1); Swig_mark_arg(i); + } else if (strcmp(argv[i],"-nofastdispatch") == 0) { + Wrapper_fast_dispatch_mode_set(0); + Swig_mark_arg(i); } else if (strcmp(argv[i],"-directors") == 0) { Hash *features_hash = Swig_cparse_features(); String *name = NewString(""); diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 96b9d7568..f51785474 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -372,6 +372,7 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { /* Loop over the functions */ for (i = 0; i < nfunc; i++) { + int fn = 0; Node *ni = Getitem(dispatch,i); Parm *pi = Getattr(ni,"wrap:parms"); int num_required = emit_num_required(pi); @@ -410,8 +411,7 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { int num_braces = 0; bool test=(Len(coll)>0 && num_arguments); if (test) { - Printf(f,"int _v=1;\n"); - + int need_v = 1; j = 0; Parm *pj = pi; while (pj) { @@ -459,6 +459,10 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { } if (emitcheck) { + if (need_v) { + Printf(f,"int _v = 1;\n"); + need_v = 0; + } if (j >= num_required) { Printf(f, "if (%s > %d) {\n", argc_template_string, j); num_braces++; @@ -466,7 +470,8 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { String *tmp=NewStringf(argv_template_string, j); Replaceall(tm,"$input", tmp); Printv(f,"{\n",tm,"}\n",NIL); - Printf(f, "if (!_v) goto fail_%s;\n", Getattr(ni, "wrap:name")); + fn = i + 1; + Printf(f, "if (!_v) goto check_%d;\n", fn); } } if (!Getattr(pj,"tmap:in:SWIGTYPE") && Getattr(pj,"tmap:typecheck:SWIGTYPE")) { @@ -491,7 +496,7 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { Printf(f, Char(lfmt),Getattr(ni,"wrap:name")); Printf(f,"}\n"); /* braces closes "if" for this method */ - Printf(f, "fail_%s:\n\n", Getattr(ni,"wrap:name")); + if (fn) Printf(f, "check_%d:\n\n", fn); Delete (lfmt); Delete(coll);