On Sunday 07 October 2001 10:51 pm, Michael Fischer wrote:
>
> Questions, comments, criticisms?

It looks like you're implementing this as a full, solitary switch.

while (*pc) {
    switch (*pc) {
    }
}

I don't see (on simple inspection) a default case, which implies that all 
functions would be in the switch.  There's two problems with that.  First, 
you can't then swap out (or add) opcode functions, which compilation units 
need to do.  They're all fixed, unless you handle opcode differentiation 
within each case.  (And there some other problems associated with that, too, 
but they're secondary.)  Second, the switch will undoubtedly grow too large 
to be efficient.  A full switch with as few as 512 branches already shows 
signs of performance degradation. [1]  Thirdly, any function calls that you 
then *do* have to make, come at the expense of the switching branch, on top 
of normal function call overhead.

I've found [2] that the fastest solution (on the platforms I've tested) are 
within the family:

while (*pc) {
    if (*pc > CORE_OPCODE_NUMBER) {
        pc = func_table[*pc]();
    } else {
        switch (*pc) {
    }
}

That keeps the switch branching small.  Do this:

while (*pc) {
    switch (*pc) {
        case : ...
        default: pc = func_table[*pc]();
    }
}

seems simpler, but introduces some potential page (or at least i-cache(?)) 
thrashing, as you've got to do a significant jump just in order to jump 
again.  The opcode comparison, followed by a small jump, behaves much nicer.

[1] Pre-Parrot testing at 
http://members.home.net/bcwarno/Perl6/spool/opcode_test_results.txt

[2] The code for my last set of benchmarks at 
http://members.home.net/bcwarno/Perl6/spool/interpreter.c

-- 
Bryan C. Warnock
[EMAIL PROTECTED]

Reply via email to