2012-03-07 5 views
-1

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

Я использовал файл размером 50 МБ, содержащий содержимое кода [], зацикленного на бенчмарке. Моя конфигурация: i7, 8gb RAM, скомпилированная с использованием 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; 
} 

EDIT: Мой вопрос, почему код переключатель быстрее? Есть ли что-то, что я делаю неправильно?

+3

Что вы хотите сказать? – orlp

+0

Мой вопрос: почему код переключения быстрее? – blez

+0

Я отредактировал мой вопрос. – blez

ответ

0

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

Корпус коммутатора более эффективен из-за оптимизации компилятора, поскольку он создает таблицу перехода, как вы уже сказали.

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

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

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