65

(This is an extremely newbie-ish question).

I've been studying a little about Virtual Machines.

Turns out a lot of them are designed very similarly to physical or theoretical computers.

I read that the JVM for example, is a 'stack machine'. What that means (and correct me if I'm wrong) is that it stores all of it's 'temporary memory' on a stack, and makes operations on this stack for all of it's opcodes.

For example, the source code 2 + 3 will be translated to bytecode similar to:

push 2
push 3
add

My question is this:

JVMs are probably written using C/C++ and such. If so, why doesn't the JVM execute the following C code: 2 + 3..? I mean, why does it need a stack, or in other VMs 'registers' - like in a physical computer?

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?

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

Again, very newbie-ish questions. Thanks for your help

5
  • 5
    Have you considered what non virtual machines are based on?
    – user40980
    Jun 8, 2014 at 20:21
  • 6
    @MichaelT You mean physical machines?
    – Aviv Cohn
    Jun 8, 2014 at 20:23
  • Of course, most Javascript VMs aren't stack machines or register machines -- V8 / IonMonkey / Chakra / etc. are VMs that implement Javascript. A "VM" is just an interpreter or JIT compiler which can implement any language the designer so desires. Jun 9, 2014 at 5:04
  • @BillyONeal So for example if I'm writing a VM for some language and I'm writing it in C: the VM parses the bytcode line 'print "hi"', and executes printf("hi");: is this considered a VM? It has no 'stack' or 'registers' and or anything.
    – Aviv Cohn
    Jun 9, 2014 at 13:25
  • @Prog: Yep, that's correct. Jun 11, 2014 at 6:05

4 Answers 4

64

A machine, virtual or not, needs a model of computation which describes how computation is carried out on it. By definition, as soon as it computes, it implements some model of computation. The question then is: What model should we choose for our VM? Physical machines are constrained by what can be effectively and efficiently done in hardware. But, as you note, virtual machines have no such constraints, they are defined in software using arbitrarily high level languages.

There are, in fact, virtual machines that are high-level as you describe. They are called programming languages. The C standard for example dedicates the bulk of its pages to defining a model for the so-called "C abstract machine" which describes how C programs behave, and by extension (as-if rule) how a conforming C compiler (or interpreter) should behave.

Of course, we usually don't call that a virtual machine. A VM is usually takes to mean something lower-level, closer to hardware, not intended to be directly programmed, designed to be executed efficiently. This selection bias means that something that accepts high-level composable code (like what you describe) wouldn't be considered a VM because is executes high-level code.

But to get the to the point, here are some reasons to make a VM (as in, something targeted by a bytecode compiler) register-based or the like. Stack and register machines are extremely simple. There's a sequence of instructions, some state, and semantics for each instruction (a function State -> State). No complex tree reductions, no operator precedence. Parsing, analysing and executing it is very simple, because it's a minimal language (syntactic sugar is compiled away) and designed to be machine-read rather than human-read.

In contrast, parsing even the simplest C-like languages is quite hard, and executing it requires non-local analyses like checking and propagating types, resolving overloads, maintaining a symbol table, resolving string identifiers, turning linear text into a precedence-driven AST, and so on. It builds on concepts that come natural to humans but have to be painstakingly reverse engineered by machines.

JVM bytecode, for example, is emitted by javac. It virtually never needs to be read or written by humans, so it's natural to gear it towards consumption by machines. If you optimized it for humans, the JVM would just on every startup read the code, parse it, analyze is, and then convert it into an intermediate representation resembling such a simplified machine model anyway. Might as well cut out the middle man.

10
  • So what you're saying is that compiling everything to instructions on the stack (i.e. System.out.println("hi"); is compiled to some instruction on a stack, int a = 7 is compiled to an instruction on the stack, etc.) makes executing the program simple and more efficient?
    – Aviv Cohn
    Jun 8, 2014 at 21:33
  • 2
    @Prog Basically, yes. But not just execution, also analysis. Everything that is done programmatically.
    – user7043
    Jun 8, 2014 at 21:42
  • 10
    @Prog You seem too focused on the specific case of 2 + 3. What about a + b? Then the values to add don't come from i.argument{1,2}, they are loaded from local variables. What about frobnicate(x[i]) + (Foo.bar() * 2)? Using this design, there is only one add operation (for int) and it works independently of how the addends were computed. Plus, an instruction that adds only integer literals would be pointless: Its result could just as well be pre-computed (i.e. instead of add(2,3) it should be push(5)).
    – user7043
    Jun 12, 2014 at 4:57
  • 2
    In Java's case, the fundamental reason to create a virtual machine was to make Java write-once, run anywhere. It separates the Java language from the runtime environment. Java runs on a wide variety of hardware where the number of registers available differ, so stack based was more flexible. In the .Net case, it was to separate the run time environment (CLR) from the several languages that compile to that byte code. In retrospect, that decision enabled .Net Core to be feasible and now it can run in operating systems it wasn't originally written for. Oct 30, 2017 at 18:15
  • 2
    The Virtual Machine approach provides the ability to compile one binary and deploy it to a wide range of hardware and operating systems. In contrast to C, the library linking and type sizes will probably be different in Linux vs. Windows and Intel vs. ARM. You can't take a binary compiled in one environment and expect it to work in one that it wasn't built for, even though the source code would still work if you recompile it in the new environment. Virtual machines separate out those details so the same binary works without having to recompile it. Oct 30, 2017 at 18:21
25

This answer focuses on the JVM, but in fact it applies to any VM.

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

They don't, but it makes the VM much simpler and portable: A VM that emulates hardware can use the same computational model than any hardware CPU.

The JVM in particular was built with portability in mind, in fact it was built so it could even be implemented in hardware (it may be hard to believe today, but the origin of Java was in the embedded world - specifically, controllers for interactive television).

If you have a goal like this, it is desirable that the VM operates as close to a physical machine as possible, because translating to actual machine code becomes easier and thus faster. Once you have the opcodes of the VM, in theory, all you have to do is translate to opcodes of the CPU the program actually runs on. In practice it is not exactly that simple.

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

Using a stack based virtual machine model has the advantage that it can be easily transferred to both register and stack machines, while the opposite is not necessarily true. A register-based VM would need to make assumptions about the number of registers, the size of the registers etc. With a stack machine, no such assumptions are necessary.

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?

Well, that's what such VMs do, they interpret bytecode. Even the JVM actually does that, at least before JIT (just-in-time) kicks in: it interprets the byte codes and executes the statements in the language the JVM was written in (typically C or C++, but there is even one written in JavaScript, Doppio). Note, however, that even such statements were translated to machine code by a compiler and actually look very similar to what the Java compiler produces - namely, they use registers and the stack to perform their work. Note the use of "interpreted" v.s. "compiled" languages becomes somewhat blurry at this point.

8
  • Of course, anything that can be implemented in software can be implemented in hardware. Also, the JVM currently (hotspot) is a JIT compiler -- it does not execute the statements in the language the JVM was written in. If it did, Java would perform terribly and would be nowhere near as viable a platform as it is today. (Hell, most Javascript implementations would be faster) Jun 9, 2014 at 5:00
  • 4
    @BillyONeal "Rather than compiling method by method, just in time, the Java HotSpot VM immediately runs the program using an interpreter, and analyzes the code as it runs to detect the critical hot spots in the program. Then it focuses the attention of a global native-code optimizer on the hot spots. " quoted from oracle.com/technetwork/java/whitepaper-135217.html#2, section "Hot Spot Detection"
    – miraculixx
    Jun 9, 2014 at 7:41
  • Yes. "Native code optimizer" == JIT compilation. There is an interpreter phase for code which doesn't appear to be "hot" to avoid JITing rarely used things. But that doesn't mean no JITing is done at all. Jun 11, 2014 at 6:06
  • Thanks for answering. What I gathered from your answer is that the reasons to emulate hardware in the VM (aka with 'stacks' or 'registers' etc.) is because it makes it easy to later compile the bytecode or the source code to actual machine code of a physical CPU. However apart from that - is there anything to gain from emulating hardware in a VM? I still don't understand why somebody designing a VM would think in terms of a 'stack machine' or 'register machine' etc. when in fact we're talking about software. Am I missing something?
    – Aviv Cohn
    Jun 11, 2014 at 21:24
  • @Prog Ok, you have a programming language, say X. How will you run its programs? You can either interpret the source or compile it to machine code, or compile it into some intermediate code. Now you have another programming language, Y, and want to implement it using X. If both implementations are interpreter, you will have the interpreter of Y running on the interpreter of X, and this will be very slow. Jun 19, 2014 at 8:46
15

Why do VMs need to be “stack machines” or “register machines” etc.?

They do not. If you need a virtual machine, it may be anything.

The existing virtual machines have appeared as solutions to the situations like: A really brilliant idea has come to my head, I have invented a new programming language! But I have to generate code. (What a boring task!) But I do not want to generate i8086 code because it's ugly, and I do not want to generate 68k code because everyone else is using Intel. There's also VAX, but I don't have any VAX, neither a computer nor a VAX book. Therefore I will generate code for some processor that does not physically exist and implement that processor in software. The spec of that VM will make a chapter in my thesis. In theory, it will be possible to compile it to native code of any processor, but that will not be me.

On the other hand, the notation like "2+3" probably will not be used by VMs in foreseeable future because it implies doing a lot of transformation before something may be executed.

2
  • Thanks for answering. So what I gathered from your answer, is that the motivation to design a VM that emulates physical CPUs is because it makes it easy to later implement compilers that compile to actual machine code. But other than that - are there any advantages to designing a VM in terms of a 'stack machine' or a 'register machine' etc.?
    – Aviv Cohn
    Jun 11, 2014 at 21:28
  • 4
    Registers require register allocation algorithms, that need both theory and debugging. A stack machine (esp a zero-operand one) can just place the data on the stack. OTOH, hardware usually implements a limited amount of registers rather than a variable-sized stack. So stacks are easier for software, registers are easier for hardware and probably therefore a bit faster. Jun 16, 2014 at 6:24
-2

To answer the actual question that was asked. The term "virtual MACHINE" means that ALL software/hardware are simulated/emulated. If you use the underlying software/hardware to execute the instructions then you do not have a VM, you have a compiler/interpreter.

3
  • is this merely your opinion or you can back it up somehow?
    – gnat
    Oct 30, 2017 at 5:00
  • @Kyrelel that's untrue. "ALL" hardware is emulated in "system" or "full" VM. Not all VMs are full. For example, BSD VM layer is named "virtual machine", despite hardware is not emulated there.
    – Netch
    Oct 30, 2017 at 10:06
  • I don't think the question is necessarily about terminology, but rather why virtual machines implement functionality that is seemingly already handled by the actual hardware
    – Ryan
    Oct 30, 2017 at 20:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.