Francis Cianfrocca wrote:
But on this point of register vs. stack machines. Most of the people
writing to the VM are language implementors, not ordinary users, and
they have a lot of sophisticated things to learn anyway. Most real
hardware supports the register-file model either natively, in
microcode, or with opcodes. I'm not convinced that the stack-based
model necessarily gives advantages over the register-based, and my
intuition says that other factors in the machine architecture are more
important.
Well ... most of the interesting problems in this area are either NP-Complete or flat out unsolvable, so it boils down to questions of what reasonably good programmers can get done in reasonable amounts of time. For example, I think there's an awful lot of optimization in GCC that most of us could live very well without. Back in the "good old days", people used to compare compilers optimized for compile speed with compilers that worked hard to generate fast code, and the typical result was that there was only a factor of two improvement in run time speed from working hard to generate fast code.
But when the code in question is a language interpreter or run-time, that's another thing entirely. In that case, I think you *do* want to work hard to squeeze the most out of the hardware. I think you *do* want to do what the vmgen/gforth project does -- exploit things in GCC that aren't part of the C language standard to squeeze every last wasted cycle out of the "inner interpreter". And if it's more efficient to manage two or three stacks than dozens of registers, I think you want a stack machine and not a register machine.
And given that you've embraced a GCC dependency, I think you *do* want to go the extra step and put in assembly language kernels for x86, x86-64 and probably PPC and SPARC and ARM architectures as well. Why should a linear algebra library like Atlas, which runs continuously for hours on a problem, be allowed to do that and not a language interpreter, which also runs continuously for hours on a problem?
Most of the recent work in VM optimization has taken place in the JVM
context, and involves extreme cleverness in regard to what code should
be compiled or recompiled to native opcodes, and when.
Well, I'm not at all familiar with the Microsoft CLR, but I suspect they're got some equally bright folks hacking on it as well.
But look at the
older literature, from before the release of Java, and you'll find a
lot of stuff that is probably more germane to dynamic-language
processing (much of it done in the Smalltalk context, but still
generic): things like detecting and hard-compiling code that is not
likely to be metaprogrammed, and tuning these code paths heuristically
during the run.
I'm not at all familiar with any of that. My background is "VLIW", vector and parallel supercomputing and FORTRAN compilers for same. As an aside, it really saddens me that the current crop of pundits bemoans the ascendancy of multi-core processors with whining about "the applications aren't ready, the software isn't ready, the languages aren't ready, the operating systems aren't ready, programmers don't know how to deal with concurrency," etc., etc. Come on, people -- Gene Amdahl formulated Amdahl's Law in 1967! There are teraflop computing platforms operating *today*! The guts of multi-media -- digital signal and image processing -- have been parallelized and vectorized since the mid-1970s!
My bottom line is this: I don't care about Perl, not even a little
tiny bit. But I'm not convinced that we've asked enough questions
about the ideal VM characteristics for supporting highly-dynamic
languages. I know little about Rubinius and have not conversed with
Evan. I'm quite impressed with Charles' work to date on JRuby, but the
JVM may not be the ideal platform for running Ruby. I don't think
we've heard the last word.
Well ... maybe we haven't heard the "last" word, but we've certainly heard the directions of the four major Ruby implementors -- if there are indeed still four. I think when all the smoke clears, at least jRuby and YARV will still be standing and will be "for all practical purposes" equivalent in performance. Rubinius in some form or another will survive and thrive, though I'm not sure it will be as a virtual machine -- I think of it more as an IDE/OS in the same sense as Squeak is to Smalltalk.
And Ruby is in a distinct class compared to other dynamic languages
because of the unusual degree to which it encourages and benefits from
metaprogramming. No, that's not to say other languages can't do
similar things. It is to say that this is part of "the Ruby way," and
I find Ruby handicapped by the huge performance penalty that
metaprogramming often imposes.
This is where I think the edge goes to Rubinius.
Concurrency primitives: at the end of the day, there is only one
primitive that is really required, and it MUST be supplied by the
hardware, not the VM. That's the atomic check-and-set operation, of
course. Threading packages for C can be and often are supplied as
pure-userland libraries.
It's not just atomic check-and-set -- it's *all* of the conveniences people expect. Message passing, monitors, lightweight processes a la Erlang/Termite, drb, Rinda, starfish, high-speed numeric vector processing -- it *all* has to be there, either in the language or in a library and supported *efficiently* by the run time on the major operating systems and hardware. Otherwise, it violates the dictum that it's possible to write FORTRAN programs in any language. 
···
--
M. Edward (Ed) Borasky, FBG, AB, PTA, PGS, MS, MNLP, NST, ACMC(P)
http://borasky-research.blogspot.com/
If God had meant for carrots to be eaten cooked, He would have given rabbits fire.