luser- -droog wrote:
) 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[i].n;
) if (tos-os < op.sig[i].n) { err = stackunderflow;
) continue; }
) for (j=0; j<op.sig[i].n; j++) { /* check types */
) /* j indexes both siq[] and op.sig[i].t[] :
) the stack and the pattern, respectively. */
)
) /* anytype matches anything */
) if (op.sig[i].t[j] == anytype) continue;
)
) /* exact match */
) if (siq[j].tag == op.sig[i].t[j]) continue;
)
) /* the numbertype pattern matches integers or reals */
) if ( op.sig[i].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[i].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[i].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[i].out > OSSIZE) error(st,stackoverflow);
) switch (op.sig[i].n) {
) case 0: op.sig[i].fp(st); break;
) case 1: op.sig[i].fp(st, siq[0]); break;
) case 2: op.sig[i].fp(st, siq[0], siq[1]); break;
) case 3: op.sig[i].fp(st, siq[0], siq[1], siq[2]); break;
) case 4: op.sig[i].fp(st, siq[0], siq[1], siq[2], siq[3]);
) break;
) case 5: op.sig[i].fp(st, siq[0], siq[1], siq[2], siq[3],
) siq[4]); break;
) case 6: op.sig[i].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?
Looks like there's a maximum of 6 arguments to check, and 3 possible
types to check against? That's just 18 bits, isn't it?
I'm not sure what you envisioned with bytemasks, but this sounds lke you
could do it with a single bitmask: simply build up a bitstring with each
of the types on the stack, and compare it to the bitmask of each op.
'anytype' is then, simply, all (three?) bits set. And 'numbertype' has
bits set on both 'int' and 'real'.
(Finding out if promotions are needed involves masking out all 'int'
argument types, shifting those to the 'real' position and then masking
against the signature bits, leaving just the 'int->float' bits)
You could also tweak it to check, say, just four arguments, and then go
into a special check for ops that need more than four arguments, which
may or may not speed up things, because you need to check fewer args
for common cases.
Depending on how many polymorphic ops there are, you could do a linear
search or perhaps some kind of trie approach.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT