Por que as VMs precisam ser "máquinas de pilha" ou "máquinas de registro" etc.?

46

(Esta é uma questão extremamente newbie-ish).

Eu tenho estudado um pouco sobre máquinas virtuais.

Acontece que muitos deles são projetados de forma muito similar a computadores físicos ou teóricos.

Eu li que a JVM, por exemplo, é uma 'stack machine'. O que isso significa (e corrija-me se estiver errado) é que ele armazena toda a 'memória temporária' em uma pilha e faz operações nesta pilha para todos os seus opcodes.

Por exemplo, o código-fonte 2 + 3 será traduzido para bytecode semelhante a:

push 2
push 3
add

Minha pergunta é esta:

As JVMs são provavelmente escritas usando C / C ++ e outras. Em caso afirmativo, por que a JVM não executa o seguinte código C: 2 + 3 ..? Quero dizer, por que precisa de uma pilha ou de outros registros de VMs - como em um computador físico?

A CPU física subjacente cuida de tudo isso. Por que os escritores de VM simplesmente executam o bytecode interpretado com instruções 'usuais' no idioma em que a VM está programada?

Por que as VMs precisam emular hardware, quando o hardware real já faz isso para nós?

Mais uma vez, perguntas muito novatas. Obrigado pela sua ajuda

    
por Aviv Cohn 08.06.2014 / 22:18
fonte

4 respostas

50

Uma máquina, virtual ou não, precisa de um modelo de computação que descreva como a computação é realizada nela. Por definição, assim que calcula, implementa algum modelo de computação. A questão então é: qual modelo devemos escolher para a nossa VM? As máquinas físicas são limitadas pelo que pode ser efetivamente e eficientemente feito em hardware. Mas, como você observou, as máquinas virtuais não têm essas restrições, elas são definidas no software usando linguagens arbitrariamente de alto nível.

Existem, na verdade, máquinas virtuais de alto nível como você descreve. Eles são chamados de linguagens de programação . O padrão C, por exemplo, dedica a maior parte de suas páginas à definição de um modelo para a chamada "máquina abstrata C" que descreve como os programas C se comportam e por extensão (como regra) como um compilador C (ou interpretador) deve se comportar.

Claro, geralmente não chamamos isso de máquina virtual. Uma VM é geralmente utilizada para significar algo de nível inferior, mais próximo do hardware, não destinado a ser diretamente programado, projetado para ser executado de forma eficiente. Esse viés de seleção significa que algo que aceita código composable de alto nível (como o que você descreve) não seria considerado uma VM porque é executado código de alto nível.

Mas para chegar ao ponto, aqui estão algumas razões para tornar uma VM (como em algo direcionado por um compilador bytecode) baseada em registro ou algo semelhante. As máquinas de pilha e registro são extremamente simples. Há uma sequência de instruções, algum estado e semântica para cada instrução (uma função State - > State). Nenhuma redução de árvore complexa, sem precedência de operador. Analisar, analisar e executar é muito simples, porque é uma linguagem mínima (o açúcar sintático é compilado) e projetado para ser lido em máquina em vez de leitura humana.

Por outro lado, analisar até mesmo as linguagens C mais simples é muito difícil, e executá-las requer análises não locais, como verificar e propagar tipos, resolver sobrecargas, manter uma tabela de símbolos, resolver identificadores string , transformando texto linear em uma AST orientada por precedência e assim por diante. Baseia-se em conceitos que são naturais aos humanos, mas que precisam ser meticulosamente submetidos a engenharia reversa por máquinas.

O bytecode da JVM, por exemplo, é emitido por javac . Ele praticamente nunca precisa ser lido ou escrito por humanos, então é natural direcioná-lo para o consumo de máquinas. Se você otimizá-lo para humanos, a JVM iria apenas em cada inicialização ler o código, analisá-lo, analisar é e, em seguida, convertê-lo em uma representação intermediária semelhante a um modelo de máquina simplificado de qualquer maneira . Pode muito bem cortar o homem do meio.

    
por 08.06.2014 / 22:50
fonte
19

Esta resposta se concentra na JVM, mas na verdade se aplica a qualquer VM.

Why do VMs need to emulate hardware, when the actual hardware already does this for us?

Eles não fazem isso, mas torna a VM muito mais simples e portátil: uma VM que emula hardware pode usar o mesmo modelo computacional do que qualquer CPU de hardware.

A JVM em particular foi construída tendo em mente a portabilidade; na verdade, ela foi construída para que pudesse ser implementada em hardware (pode ser difícil acreditar hoje, mas a origem do Java estava no mundo incorporado - especificamente, controladores para televisão interativa).

Se você tem uma meta como essa, é desejável que a VM opere o mais próximo possível de uma máquina física, porque a tradução para o código da máquina real se torna mais fácil e, portanto, mais rápida. Uma vez que você tenha os opcodes da VM, em teoria, tudo que você precisa fazer é traduzir para opcodes da CPU que o programa realmente roda. Na prática, não é exatamente assim tão simples.

I mean, why does it need a stack, or in other VMs 'registers' - like in a physical computer?

O uso de um modelo de máquina virtual baseado em pilha tem a vantagem de poder ser facilmente transferido para máquinas de registro e de pilha, enquanto o oposto não é necessariamente verdadeiro. Uma VM baseada em registros precisaria fazer suposições sobre o número de registradores, o tamanho dos registradores, etc. Com uma máquina de empilhamento, tais suposições não são necessárias.

The underlying physical CPU takes care of all of this. Why don't VM writers simply execute the interpreted bytecode with 'usual' instructions in the language the VM is programmed with?

Bem, é isso que essas VMs fazem, elas interpretam o código de bytes. Até mesmo a JVM realmente faz isso, pelo menos antes do JIT (just-in-time) entrar: ele interpreta os códigos de byte e executa as instruções na linguagem em que a JVM foi escrita (normalmente C ou C ++, mas existe até uma escrita em JavaScript, Doppio ). Note, no entanto, que mesmo tais declarações foram traduzidas para código de máquina por um compilador e realmente parecem muito semelhantes ao que o compilador Java produz - a saber, eles usam registradores e a pilha para executar seu trabalho. Observe o uso de "interpretado" v.s. Os idiomas "compilados" tornam-se um pouco desfocados neste momento.

    
por 09.06.2014 / 00:57
fonte
9

Por que as VMs precisam ser "máquinas de pilha" ou "máquinas de registro", etc.?

Eles não. Se você precisar de uma máquina virtual, pode ser qualquer coisa.

As máquinas virtuais existentes surgiram como soluções para situações como: Uma ideia realmente brilhante veio à minha cabeça, eu inventei uma nova linguagem de programação! Mas eu tenho que gerar código. (Que tarefa chata!) Mas eu não quero gerar código i8086 porque é feio, e eu não quero gerar código 68k porque todo mundo está usando a Intel. Há também o VAX, mas eu não tenho nenhum VAX, nem um computador nem um livro do VAX. Por isso vou gerar código para algum processador que não existe fisicamente e implementar esse processador em software. A especificação dessa VM fará um capítulo na minha tese. Em teoria, será possível compilá-lo para código nativo de qualquer processador, mas isso não será eu.

Por outro lado, a notação como "2 + 3" provavelmente não será usada por VMs no futuro previsível porque implica em fazer muita transformação antes que algo possa ser executado.

    
por 09.06.2014 / 13:09
fonte
-2

Para responder à pergunta real que foi feita. O termo "MÁQUINA virtual" significa que TODOS os softwares / hardwares são simulados / emulados. Se você usar o software / hardware subjacente para executar as instruções, então você não tem uma VM, você tem um compilador / intérprete.

    
por 30.10.2017 / 02:03
fonte