if I undestood it correctly, computed gotos are used to reduce the branching in 
interpreter loops(a head moving through data and then executing something 
depending on the read value).

>From one of your links: 
    
    
    int interp_switch(unsigned char* code, int initval) {
        int pc = 0;
        int val = initval;
        
        while (1) {
            switch (code[pc++]) { // branch depending on the value
                case OP_HALT:
                    return val;
                case OP_INC:
                    val++;
                    break; // branch to the end of the switch statement
                case OP_DEC:
                    val--;
                    break;
                case OP_MUL2:
                    val *= 2;
                    break;
                case OP_DIV2:
                    val /= 2;
                    break;
                case OP_ADD7:
                    val += 7;
                    break;
                case OP_NEG:
                    val = -val;
                    break;
                default:
                    return val;
            }
        } // branch to the beginning of the loop. The compiler might optimise 
it to make the break jump directly to the top
    }
    
    
    Run

So in this unoptimised case we have two or three branches per interpreted 
instruction.

The computed goto allows us to reduce it to only one branch per instruction: 
    
    
    int interp_cgoto(unsigned char* code, int initval) {
        /* The indices of labels in the dispatch_table are the relevant opcodes
        */
        static void* dispatch_table[] = {
            &&do_halt, &&do_inc, &&do_dec, &&do_mul2,
            &&do_div2, &&do_add7, &&do_neg};
        #define DISPATCH() goto *dispatch_table[code[pc++]]
        
        int pc = 0;
        int val = initval;
        
        DISPATCH(); // jump to the next instruction
        while (1) {
            do_halt:
                return val;
            do_inc:
                val++;
                DISPATCH(); // directly jump to the next instruction
            do_dec:
                val--;
                DISPATCH();
            do_mul2:
                val *= 2;
                DISPATCH();
            do_div2:
                val /= 2;
                DISPATCH();
            do_add7:
                val += 7;
                DISPATCH();
            do_neg:
                val = -val;
                DISPATCH();
        }
    }
    
    
    Run

Reply via email to