Pergunta

I irá implementar uma máquina virtual em x86 e gostaria de saber que tipo de projeto renderia melhores resultados. O que devo concentrar-se em esmagar o suco? Eu vou para implementar toda a máquina virtual em x86 montagem.

Eu não tenho muito instruções e posso escolher sua forma. As instruções do projeto diretamente para a sintaxe do Smalltalk em blocos. Eu dou o desenho de instrução Eu estava pensando em:

^ ...       # return
^null     # return nothing
object    # address to object
... selector: ... # message pass (in this case arity:1 selector: #selector:)
var := ... # set
var # get

O tipo de VM eu estava pensando:

mov eax, [esi]
add esi, 2
mov ecx, eax
and eax, 0xff
and ecx, 0xff00 # *256
shr ecx, 5          # *8
jmp [ecx*4 + operations]
align 8:
    operations:
dd retnull
dd ret
# so on...
    retnull:          # jumps here at retnul
# ... retnull action
    ret:
# ... ret action
#etc.

Não comece perguntando por que eu preciso de mais uma implementação da máquina virtual. rotinas interpretativas não são coisas estoque que você acabou de pegar sempre que você precisar deles. A maioria das máquinas virtuais que você está propondo em outros lugares são ponderadas no sentido de portabilidade com o custo de desempenho. Meu objetivo não é a portabilidade, o meu objetivo é o desempenho.

A razão deste intérprete é necessária em tudo é porque blocos Smalltalk não acabam começado interpretado da mesma maneira:

A := B subclass: [
    def a:x [^ x*x]
    clmet b [...]
    def c [...]
    def d [...]
]

[ 2 < x ] whileTrue: [...]

(i isNeat) ifTrue: [...] ifFalse: [...]

List fromBlock: [
    "carrots"
    "apples"
    "oranges" toUpper
]

Eu preciso o real benefício proveniente das rotinas interpretativas, que é a escolha do contexto em que a ler o programa no Claro, bom compilador deve apenas a maior parte do tempo de compilação dos casos óbvios, como:. 'IfTrue: ifFalse' ou 'whileTrue:', ou o exemplo lista. A necessidade de intérprete não desaparece, porque você sempre pode bater em um caso em que você não pode ter certeza que o bloco recebe o tratamento que você espera.

Foi útil?

Solução

Vejo que há alguma confusão sobre portabilidade aqui, então eu me sinto obrigado a esclarecer as coisas um pouco. Estas são as minhas opiniões humildes assim que você é, é claro, livre para se opor contra eles.

Eu suponho que você deparei http://www.complang.tuwien.ac .at / trás / rosqueamento / se considere escrever VM sério, então eu não vou me debruçar sobre as técnicas descritas.

Já mencionado, visando uma VM tem algumas vantagens, tais como tamanho reduzido código, complexidade compilador reduzido (muitas vezes se traduz em compilação mais rápido), portabilidade (note que o ponto de uma VM é a portabilidade do idioma , de modo que não importa se o próprio VM não é portátil).

Considerando natureza dinâmica do seu exemplo, a sua VM vai se assemelhar a um JIT compilador mais do que outros mais populares. Assim, apesar S.Lott perdeu o ponto, neste caso, a sua menção de Forth é muito no local. Se eu fosse para projetar uma VM para uma linguagem muito dinâmico, gostaria de separar interpretação em duas etapas;

  1. A fase de produção que consulta um fluxo de AST na demanda e transforma-lo para uma forma mais significativa (por exemplo, tendo um bloco, decidir se ele deve ser executado imediatamente ou armazenado em algum lugar para execução posterior) a possibilidade de introduzir novos tipos de fichas. Essencialmente, você recuperar a informação sensível ao contexto que pode ser perdida na análise aqui.

  2. Um estágio consumidor buscar a corrente gerada a partir de 1 e executa-lo cegamente como qualquer outra máquina. Se você faz Forth como, você pode apenas apertar um fluxo armazenado e ser feito com ele em vez de ponteiro de instrução salto ao redor.

Como você diz, apenas imitando a forma como o trabalho do processador mínima de outra maneira não realiza qualquer dinamismo (ou qualquer outro valor de recurso a mínima, como a segurança) que você precisa. Caso contrário, você estaria escrevendo um compilador.

Claro, você pode adicionar otimizações arbitrariamente comlex na fase 1.

Outras dicas

Se você quiser algo muito rápido, tente usar LLVM . Ele pode gerar código nativo para a maioria dos processadores de uma descrição do programa de alto nível. Você pode ir com seu próprio linguagem assembly ou gerar a estrutura llvm pular a fase de montagem, dependendo do que você achar mais conveniente.

Eu não tenho certeza se é o melhor para o seu problema, mas é definitivamente o que eu usaria se eu iria fazer algum desempenho de execução crítico de código que não pode ser compilado com o resto do programa.

O ponto de um intérprete é portabilidade, a maior parte do tempo. A abordagem mais rápido que eu posso pensar é para gerar x86 código na memória diretamente, assim como compiladores JIT fazer, mas, em seguida, é claro, você não tem um intérprete mais. Você tem um compilador.

No entanto, não estou certo de escrever o intérprete em assembler lhe dará o melhor desempenho (a menos que você é um guru assembler e seu projeto é muito limitado em escopo). Usando uma linguagem de alto nível pode ajudá-lo a se concentrar em melhores algoritmos para, digamos, pesquisa símbolo e registrar estratégias de alocação.

você pode acelerar sua rotina de despacho com um conjunto de instruções unencoded a:

mov eax, [esi]
add esi, 4
add eax, pOpcodeTable
jmp eax

que deve ter uma sobrecarga <4 ciclos para cada expedição de CPU> Pentium 4.

Como disso, por motivos de desempenho é melhor para incrementar ESI (IP) em cada rotina primitivo porque as chances são altas que o incremento pode ser emparelhado com outras instruções:

mov eax, [esi]
add eax, pOpcodeTable
jmp eax

~ 1-2 cylces sobrecarga.

Eu tenho que perguntar, por que criar uma máquina virtual com foco em performance? Porque não basta escrever x86 código diretamente? Nada pode, eventualmente, ser mais rápido.

Se você quiser um muito Idioma rápido interpretado, olhada Forth . Seu design é muito arrumado e muito fácil de copiar.

Se você não gosta de JIT e seu objetivo não é a portabilidade. Eu acho que você pode se interessar por href="http://code.google.com/p/nativeclient" rel="nofollow noreferrer"> NativeClient projeto Google . Eles fazem estática analista, sandboxing e outros. Eles permitem que o host executar instruções RAW x86.

scroll top