add the fast dispatch option/feature
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7950 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
91d4692367
commit
251014efcb
3 changed files with 166 additions and 4 deletions
|
|
@ -59,6 +59,7 @@ static const char *usage1 = (const char*)"\
|
||||||
-features directors,autodoc=1 \n\
|
-features directors,autodoc=1 \n\
|
||||||
if not explicit value is given to the feature, a '1' is used \n\
|
if not explicit value is given to the feature, a '1' is used \n\
|
||||||
-fvirtual - Compile in virtual elimination mode\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\
|
-Fstandard - Display error/warning messages in commonly used format\n\
|
||||||
-Fmicrosoft - Display error/warning messages in Microsoft format\n\
|
-Fmicrosoft - Display error/warning messages in Microsoft format\n\
|
||||||
-help - This output\n\
|
-help - This output\n\
|
||||||
|
|
@ -388,6 +389,9 @@ void SWIG_getoptions(int argc, char *argv[])
|
||||||
} else if (strcmp(argv[i],"-fvirtual") == 0) {
|
} else if (strcmp(argv[i],"-fvirtual") == 0) {
|
||||||
Wrapper_virtual_elimination_mode_set(1);
|
Wrapper_virtual_elimination_mode_set(1);
|
||||||
Swig_mark_arg(i);
|
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) {
|
} else if (strcmp(argv[i],"-directors") == 0) {
|
||||||
Hash *features_hash = Swig_cparse_features();
|
Hash *features_hash = Swig_cparse_features();
|
||||||
String *name = NewString("");
|
String *name = NewString("");
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,13 @@ struct Overloaded {
|
||||||
int error; /* Ambiguity error */
|
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()
|
* Swig_overload_rank()
|
||||||
*
|
*
|
||||||
|
|
@ -290,9 +297,9 @@ Swig_overload_rank(Node *n, bool script_lang_wrapping) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
// /* -----------------------------------------------------------------------------
|
||||||
* print_typecheck()
|
// * print_typecheck()
|
||||||
* ----------------------------------------------------------------------------- */
|
// * ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
print_typecheck(String *f, int j, Parm *pj) {
|
print_typecheck(String *f, int j, Parm *pj) {
|
||||||
|
|
@ -347,8 +354,159 @@ ReplaceFormat (const String_or_char *fmt, int j) {
|
||||||
* the regular function arguments.
|
* 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<nfunc; k++) {
|
||||||
|
Node *nk = Getitem(dispatch,k);
|
||||||
|
Parm *pk = Getattr(nk,"wrap:parms");
|
||||||
|
int nrk = emit_num_required(pk);
|
||||||
|
int nak = emit_num_arguments(pk);
|
||||||
|
if ((nrk>=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<Len(coll) && !emitcheck; k++) {
|
||||||
|
Node *nk = Getitem(coll, k);
|
||||||
|
Parm *pk = Getattr(nk,"wrap:parms");
|
||||||
|
int nak=emit_num_arguments(pk);
|
||||||
|
if (nak<=j) continue;
|
||||||
|
int l=0;
|
||||||
|
Parm *pl=pk;
|
||||||
|
/* finds arg j on the collider wrapper */
|
||||||
|
while(pl && l<=j) {
|
||||||
|
if (checkAttribute(pl,"tmap:in:numinputs","0")) {
|
||||||
|
pl = Getattr(pl,"tmap:in:next");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (l==j) {
|
||||||
|
/* we are at arg j, so we compare the tmaps now */
|
||||||
|
String *tml = Getattr(pl, "tmap:typecheck");
|
||||||
|
/* normalise it before comparing */
|
||||||
|
if (tml) Replaceid(tml,Getattr(pl,"lname"),"_v");
|
||||||
|
if (!tml || Cmp(tm, tml)) emitcheck=1;
|
||||||
|
//printf("tmap: %s[%d] (%d) => %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 *
|
String *
|
||||||
Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *maxargs) {
|
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;
|
int i,j;
|
||||||
|
|
||||||
*maxargs = 1;
|
*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--)
|
for (/* empty */; num_braces > 0; num_braces--)
|
||||||
Printf(f, "}\n");
|
Printf(f, "}\n");
|
||||||
Printf(f,"}\n"); /* braces closes "if" for this method */
|
Printf(f,"}\n"); /* braces closes "if" for this method */
|
||||||
Delattr(ni,"wrap:parms");
|
|
||||||
}
|
}
|
||||||
Delete(dispatch);
|
Delete(dispatch);
|
||||||
return f;
|
return f;
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,7 @@ int is_member_director(Node* member);
|
||||||
void Wrapper_virtual_elimination_mode_set(int);
|
void Wrapper_virtual_elimination_mode_set(int);
|
||||||
void Wrapper_director_mode_set(int);
|
void Wrapper_director_mode_set(int);
|
||||||
void Wrapper_director_protected_mode_set(int);
|
void Wrapper_director_protected_mode_set(int);
|
||||||
|
void Wrapper_fast_dispatch_mode_set(int);
|
||||||
|
|
||||||
void clean_overloaded(Node *n);
|
void clean_overloaded(Node *n);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue