L
luser- -droog
I'm working on a redesign of my postscript interpreter; and I'm
trying to upgrade each module as I lock it in. Gprof runs of my
current program (code.google.com/p/xpost) constantly list
opexec() as the worst offender. And it really is a mess.
It attempts to perform the tasks of selecting the appropriate
form of polymorphic operators, checking the types on the
stack, and calling the resulting operator function through a
variable-argument switch-rig.
/* Execute an operator by opcode.
Examines stack to match against the patterns in signature.
Calls operator function with arguments.
if no signatures for the opcode match,
it issues an error corresponding to the last failed check
(either stackunderflow or typecheck)
*/
void opexec (state *st, size opcode) {
oper op = optab[opcode];
int i, j;
bool pass;
object *siq = tos; /* stack-segment in question */
int err = typecheck;
current_op = opcode;
if (op.n == 0) error(st,unregistered);
for (i=0; i<op.n; i++) { /* try each signature */
pass = true;
current_op_sig = i;
siq = tos-op.sig.n;
if (tos-os < op.sig.n) { err = stackunderflow;
continue; }
for (j=0; j<op.sig.n; j++) { /* check types */
/* j indexes both siq[] and op.sig.t[] :
the stack and the pattern, respectively. */
/* anytype matches anything */
if (op.sig.t[j] == anytype) continue;
/* exact match */
if (siq[j].tag == op.sig.t[j]) continue;
/* the numbertype pattern matches integers or reals */
if ( op.sig.t[j] == numbertype
&& ( siq[j].tag == integertype
|| siq[j].tag == realtype) ) continue;
/* the floattype pattern causes automatic coercion
of integers to reals, ie. ints float up */
if ( op.sig.t[j] == floattype ) {
if (siq[j].tag == integertype) promote(siq[j]);
if (siq[j].tag == realtype) continue;
}
/* the proctype matches executable arrays */
if (op.sig.t[j] == proctype
&& siq[j].tag == arraytype
&& siq[j].flags.lit == 0) continue;
/* all these possibilities failed */
pass = false;
err = typecheck;
break;
}
if (pass) goto call;
}
tos = siq; /* pop the stack to the 'stack in question' */
error(st,err); /* pop before error since error will adjust the
stack */
return;
call: /* pass args bottom-up */
tos = siq; /* pop the stack to the 'stack in question' */
/* room for output? */
if (tos-os + op.sig.out > OSSIZE) error(st,stackoverflow);
switch (op.sig.n) {
case 0: op.sig.fp(st); break;
case 1: op.sig.fp(st, siq[0]); break;
case 2: op.sig.fp(st, siq[0], siq[1]); break;
case 3: op.sig.fp(st, siq[0], siq[1], siq[2]); break;
case 4: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3]);
break;
case 5: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3],
siq[4]); break;
case 6: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3],
siq[4], siq[5]); break;
default: error(st,unregistered);
}
}
So I had this great idea to do bitmasks and talked it up in clp
http://groups.google.com/group/comp.lang.postscript/browse_thread/thread/e639638484f4fa56#
but I never get much feedback there on this sort of thing.
I think I can replace my type arrays (op.sig[].t[]) with a
big integer filled with byte masks and I can accept or
reject a candidate function with an & and a ==.
But a problem arises with the "anytype" pattern.
The two options I conceive are
* multiple patterns checking each bit of just the relevant
nibble of the byte.
* devoting an entire bit to valid/invalid.
And it seems I'm pouting about these choices.
I don't like either one and I can't think of anything else.
I suppose I haven't even really formulated a question here.
Thoughts/Ramblings/Anecdotes anyone?
trying to upgrade each module as I lock it in. Gprof runs of my
current program (code.google.com/p/xpost) constantly list
opexec() as the worst offender. And it really is a mess.
It attempts to perform the tasks of selecting the appropriate
form of polymorphic operators, checking the types on the
stack, and calling the resulting operator function through a
variable-argument switch-rig.
/* Execute an operator by opcode.
Examines stack to match against the patterns in signature.
Calls operator function with arguments.
if no signatures for the opcode match,
it issues an error corresponding to the last failed check
(either stackunderflow or typecheck)
*/
void opexec (state *st, size opcode) {
oper op = optab[opcode];
int i, j;
bool pass;
object *siq = tos; /* stack-segment in question */
int err = typecheck;
current_op = opcode;
if (op.n == 0) error(st,unregistered);
for (i=0; i<op.n; i++) { /* try each signature */
pass = true;
current_op_sig = i;
siq = tos-op.sig.n;
if (tos-os < op.sig.n) { err = stackunderflow;
continue; }
for (j=0; j<op.sig.n; j++) { /* check types */
/* j indexes both siq[] and op.sig.t[] :
the stack and the pattern, respectively. */
/* anytype matches anything */
if (op.sig.t[j] == anytype) continue;
/* exact match */
if (siq[j].tag == op.sig.t[j]) continue;
/* the numbertype pattern matches integers or reals */
if ( op.sig.t[j] == numbertype
&& ( siq[j].tag == integertype
|| siq[j].tag == realtype) ) continue;
/* the floattype pattern causes automatic coercion
of integers to reals, ie. ints float up */
if ( op.sig.t[j] == floattype ) {
if (siq[j].tag == integertype) promote(siq[j]);
if (siq[j].tag == realtype) continue;
}
/* the proctype matches executable arrays */
if (op.sig.t[j] == proctype
&& siq[j].tag == arraytype
&& siq[j].flags.lit == 0) continue;
/* all these possibilities failed */
pass = false;
err = typecheck;
break;
}
if (pass) goto call;
}
tos = siq; /* pop the stack to the 'stack in question' */
error(st,err); /* pop before error since error will adjust the
stack */
return;
call: /* pass args bottom-up */
tos = siq; /* pop the stack to the 'stack in question' */
/* room for output? */
if (tos-os + op.sig.out > OSSIZE) error(st,stackoverflow);
switch (op.sig.n) {
case 0: op.sig.fp(st); break;
case 1: op.sig.fp(st, siq[0]); break;
case 2: op.sig.fp(st, siq[0], siq[1]); break;
case 3: op.sig.fp(st, siq[0], siq[1], siq[2]); break;
case 4: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3]);
break;
case 5: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3],
siq[4]); break;
case 6: op.sig.fp(st, siq[0], siq[1], siq[2], siq[3],
siq[4], siq[5]); break;
default: error(st,unregistered);
}
}
So I had this great idea to do bitmasks and talked it up in clp
http://groups.google.com/group/comp.lang.postscript/browse_thread/thread/e639638484f4fa56#
but I never get much feedback there on this sort of thing.
I think I can replace my type arrays (op.sig[].t[]) with a
big integer filled with byte masks and I can accept or
reject a candidate function with an & and a ==.
But a problem arises with the "anytype" pattern.
The two options I conceive are
* multiple patterns checking each bit of just the relevant
nibble of the byte.
* devoting an entire bit to valid/invalid.
And it seems I'm pouting about these choices.
I don't like either one and I can't think of anything else.
I suppose I haven't even really formulated a question here.
Thoughts/Ramblings/Anecdotes anyone?