From 251014efcb2c16029e9bad21b36f2bf1d09c4858 Mon Sep 17 00:00:00 2001 From: Marcelo Matus Date: Thu, 8 Dec 2005 08:54:05 +0000 Subject: [PATCH] add the fast dispatch option/feature git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7950 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Source/Modules/main.cxx | 4 + Source/Modules/overload.cxx | 165 +++++++++++++++++++++++++++++++++++- Source/Modules/swigmod.h | 1 + 3 files changed, 166 insertions(+), 4 deletions(-) diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 836bc3ac0..1e617d4bf 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -59,6 +59,7 @@ 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\ -Fstandard - Display error/warning messages in commonly used format\n\ -Fmicrosoft - Display error/warning messages in Microsoft format\n\ -help - This output\n\ @@ -388,6 +389,9 @@ 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) { + Wrapper_fast_dispatch_mode_set(1); + 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 6f72449dc..96b9d7568 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -28,6 +28,13 @@ struct Overloaded { int error; /* Ambiguity error */ }; +static int fast_dispatch_mode = 0; + +/* Set fast_dispatch_mode */ +void Wrapper_fast_dispatch_mode_set(int flag) { + fast_dispatch_mode = flag; +} + /* ----------------------------------------------------------------------------- * Swig_overload_rank() * @@ -290,9 +297,9 @@ Swig_overload_rank(Node *n, bool script_lang_wrapping) { return result; } -/* ----------------------------------------------------------------------------- - * print_typecheck() - * ----------------------------------------------------------------------------- */ +// /* ----------------------------------------------------------------------------- +// * print_typecheck() +// * ----------------------------------------------------------------------------- */ static bool print_typecheck(String *f, int j, Parm *pj) { @@ -347,8 +354,159 @@ ReplaceFormat (const String_or_char *fmt, int j) { * the regular function arguments. * ----------------------------------------------------------------------------- */ +/* + Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586). +*/ +String * +Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { + int i,j; + + *maxargs = 1; + + String *f = NewString(""); + + /* Get a list of methods ranked by precedence values and argument count */ + List *dispatch = Swig_overload_rank(n, true); + int nfunc = Len(dispatch); + + /* Loop over the functions */ + + for (i = 0; i < nfunc; i++) { + Node *ni = Getitem(dispatch,i); + Parm *pi = Getattr(ni,"wrap:parms"); + int num_required = emit_num_required(pi); + int num_arguments = emit_num_arguments(pi); + if (num_arguments > *maxargs) *maxargs = num_arguments; + int varargs = emit_isvarargs(pi); + + if (!varargs) { + if (num_required == num_arguments) { + Printf(f,"if (%s == %d) {\n", argc_template_string, num_required); + } else { + Printf(f,"if ((%s >= %d) && (%s <= %d)) {\n", + argc_template_string, num_required, + argc_template_string, num_arguments); + } + } else { + Printf(f,"if (%s >= %d) {\n", argc_template_string, num_required); + } + + /* create a list with the wrappers that collide with the + current one based on argument number */ + List *coll=NewList(); + for (int k=i+1; k=num_required && nrk<=num_arguments) || + (nak>=num_required && nak<=num_arguments) || + (nrk<=num_required && nak>=num_arguments)) + Append(coll, nk); + } + + // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll)); + + int num_braces = 0; + bool test=(Len(coll)>0 && num_arguments); + if (test) { + Printf(f,"int _v=1;\n"); + + j = 0; + Parm *pj = pi; + while (pj) { + if (checkAttribute(pj,"tmap:in:numinputs","0")) { + pj = Getattr(pj,"tmap:in:next"); + continue; + } + + String *tm = Getattr(pj,"tmap:typecheck"); + if (tm) { + /* normalise for comparison later */ + Replaceid(tm,Getattr(pj,"lname"),"_v"); + + /* if all the wrappers have the same type check on this + argument we can optimize it out */ + bool emitcheck=0; + for (int k=0; k %s\n\n", + // Char(Getattr(nk, "sym:name")), + // l, emitcheck, tml?Char(tml):0); + } + Parm *pl1 = Getattr(pl,"tmap:in:next"); + if (pl1) pl = pl1; + else pl = nextSibling(pl); + l++; + } + } + + if (emitcheck) { + if (j >= num_required) { + Printf(f, "if (%s > %d) {\n", argc_template_string, j); + num_braces++; + } + 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")); + } + } + if (!Getattr(pj,"tmap:in:SWIGTYPE") && Getattr(pj,"tmap:typecheck:SWIGTYPE")) { + /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */ + Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni), + "Overloaded %s(%s) with no explicit typecheck typemap for arg %d of type '%s'\n", + Getattr(n,"name"),ParmList_str_defaultargs(pi), + j+1, SwigType_str(Getattr(pj,"type"),0)); + } + Parm *pj1 = Getattr(pj,"tmap:in:next"); + if (pj1) pj = pj1; + else pj = nextSibling(pj); + j++; + } + } + + /* close braces */ + for (/* empty */; num_braces > 0; num_braces--) Printf(f, "}\n"); + + + String *lfmt = ReplaceFormat (fmt, num_arguments); + 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")); + + Delete (lfmt); + Delete(coll); + } + Delete(dispatch); + return f; +} + String * Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *maxargs) { + + if (fast_dispatch_mode || GetFlag(n,"feature:fastdispatch")) { + return Swig_overload_dispatch_fast(n, fmt, maxargs); + } + int i,j; *maxargs = 1; @@ -423,7 +581,6 @@ Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *maxargs) { for (/* empty */; num_braces > 0; num_braces--) Printf(f, "}\n"); Printf(f,"}\n"); /* braces closes "if" for this method */ - Delattr(ni,"wrap:parms"); } Delete(dispatch); return f; diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index bea35544e..13e38ce44 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -350,6 +350,7 @@ int is_member_director(Node* member); void Wrapper_virtual_elimination_mode_set(int); void Wrapper_director_mode_set(int); void Wrapper_director_protected_mode_set(int); +void Wrapper_fast_dispatch_mode_set(int); void clean_overloaded(Node *n);