Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

(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

share|improve this question
3  
Have you considered what non virtual machines are based on? –  MichaelT Jun 8 at 20:21
1  
@MichaelT You mean physical machines? –  Aviv Cohn Jun 8 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. –  Billy ONeal Jun 9 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 at 13:25
    
@Prog: Yep, that's correct. –  Billy ONeal Jun 11 at 6:05

3 Answers 3

up vote 23 down vote accepted

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.

share|improve this answer
    
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 at 21:33
2  
@Prog Basically, yes. But not just execution, also analysis. Everything that is done programmatically. –  delnan Jun 8 at 21:42
    
Still, I don't understand why 2 + 3 is compiled to push 2 push 3 add. The add step at the end is executed by the JVM anyway by running the C code 2 + 3. There's no other way for the programmers of the JVM to do this. Why not compile it to 2 + 3, and have the JVM just execute the C code 2 + 3 (assuming it's written in C) right away? –  Aviv Cohn Jun 9 at 13:39
    
@Prog The JVM author can't just write 2 + 3 in the JVM source code because the JVM has to work with any program doing any operations in any order. Building C source code and deferring to a C implementation just pushes the same problem into the C implementation (and can't be done easily, let alone efficiently). There has to be some data structure that describes the program, so that it can be interpreted and JIT compiled, and "human readable source code" is an awful choice of data structure for reasons outlined above. –  delnan Jun 9 at 13:59
1  
@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)). –  delnan Jun 12 at 4:57

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.

share|improve this answer
    
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) –  Billy ONeal Jun 9 at 5:00
1  
@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 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. –  Billy ONeal Jun 11 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 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. –  18446744073709551615 Jun 19 at 8:46

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.

share|improve this answer
    
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 at 21:28
    
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. –  18446744073709551615 Jun 16 at 6:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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