Простой байт-код переводчик - PullRequest
0 голосов
/ 07 марта 2012

Я пытаюсь построить быстрый JIT с использованием C / C ++.Он должен перевести мой байт-код в IA32.Да, я знаю о libjit и подобных, но я уверен, что они не проще, чем это.Я думал, что нашел более быстрый способ построения инструкции, но я ошибся - традиционный метод switch / case примерно в 2 раза быстрее моего.Мой способ - скопировать целый блок, а затем заполнить шаблон.Я знаю, что switch / case на современном компиляторе создает таблицу переходов, поэтому у меня не было реализации таблицы переходов.

Я использовал файл размером 50 Мб, содержащий содержимое кода [], зацикленного для сравнения.Моя конфигурация: i7, оперативная память 8 ГБ, скомпилированная с использованием VS2010.

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>

//unsigned char code[] = {1,2,3,4,4};

void mycopy(unsigned char* to, unsigned char* from, int size) {
    int i = 0;
    while(i < size) {
        /*if (i < size-3) {
            if (*(unsigned int*) &from[i] == 0xFFFFFFFF) {
                *(unsigned int*) &to[i] = 0xC3C3C3C3;
                i += 4;
                continue;
            }
        }*/

        to[i] = from[i];
        i++;
    } 
}

void translateA(unsigned char* code, unsigned char* output, int size) {

    unsigned char A[] = { 3, 1, 1, 1 }; // { size, <bytes...> }
    unsigned char B[] = { 2, 2, 2 };
    unsigned char C[] = { 8, 3, 3, 3, 3, 0xFF, 0xFF, 0xFF, 0xFF };
    unsigned char D[] = { 1, 4 };

    void* templat[] = { &A, &B, &C, &D };

    int i = 0;
    int total = 0;
    while(i < size) {
        int op_index = (int) code[i] - 1;
        unsigned char* instr_buffer = (unsigned char*) templat[op_index];
        int size = (int) instr_buffer[0];
        instr_buffer++;
        mycopy(output+total, instr_buffer,size);
        total += size;
        i++;
    }
}




void translateB(unsigned char* code, unsigned char* output, int size) {
    for(int i = 0; i < size; i++) {
        switch(code[i]) {
            case 1:
                output[0] = 1;
                output[1] = 1;
                output[2] = 1;
                output += 3;
                break;
            case 2:
                output[0] = 2;
                output[1] = 2;
                output += 2;
                break;
            case 3: 
                output[0] = 3;
                output[1] = 3;
                output[2] = 3;
                output[3] = 3;
                output[4] = 0xC3;
                output[5] = 0xC3;
                output[6] = 0xC3;
                output[7] = 0xC3;               
                output += 8;            
                break;
            case 4:
                output[0] = 4;
                output++;
                break;
        }
    }
}

int main(int argc, char* argv[]) {
    // load the 'code' to an array
    FILE* f = fopen("testops.bin", "r+");

    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    unsigned char* code = (unsigned char*) malloc(fsize);
    fread(code, fsize, 1, f);
    fclose(f);

    unsigned char* output = (unsigned char*) malloc(fsize*10);
    memset(output, 0x7A, fsize*10);

    // benchmark it
    time_t start = clock();

    // Replace with translateB. It's ~2x faster
    translateA(code, output, fsize);

    printf("\nelapsed %fs\n\n", (float) (clock()-start) / 1000); 

    printf("OUTPUT: ");
    for(int i=0;i<1024;i++) {
        if (output[i] == 0x7A) break;
        printf("%X", output[i]); 
    }

    printf("\n");

    system("PAUSE");
    return 0;
}

РЕДАКТИРОВАТЬ: Мой вопрос, почему код коммутатора быстрее?Я что-то не так делаю?

1 Ответ

0 голосов
/ 08 марта 2012

Постройте, затем разберите вашу программу, вы получите ответ.

Случай переключения более эффективен благодаря оптимизации компилятора, поскольку он создает таблицу переходов, как вы уже сказали.

Ваш метод выполняет поиск адресов и имеет еще один вызов функции и цикл для каждого байт-кода.

Кроме того, почему вы используете while для цикла, номер итерации которого вы знаете? Компилятор может иметь дополнительную оптимизацию для цикла for.

И с переключателем на 4 случая я не уверен, что ваш компилятор создаст таблицу переходов, поэтому реальные примеры могут быть еще быстрее.

...