Live Objects All the Way Down: Removing the Barriers Between Apps and VMs
programming-journal.org
programming-journal.org
Section 5.3.3 talks about some drawbacks, and there are more in "8. Conclusions" and "9. Future Work."
> Today, Bee is far from finished, yet we know all required functionalities can be implemented. Furthermore, the resulting code is fully object oriented and can take advantage of all the benefits that a high-level environment brings. The main remaining question to be answered is what is the maximum performance to expect from the system. We believe that the answer to that question will be highly positive, and that we will be able to unravel the mystery very soon.
...
> Current implementation of Bee is more than 10x slower than the hosted environment [...]
So, interesting work in progress, maybe check back later?
[1] http://esug.org/data/ESUG2014/IWST/Papers/iwst2014_Design%20... [2] https://github.com/aucerna/bee-dmr
Here's the pdf for this 2023 paper:
When run like this, the bytecode interpreter, runtime system and JIT compiler are all regular Java that can be debugged, edited, explored in the IDE, recompiled quickly and so on. Only the GC is provided by the host system. If you compile it to native code, the GC is also written in Java (with some special conventions to allow for convenient direct memory access).
What's most interesting is that Espresso isn't a direct translation of what a classical C++ VM would look like. It's built on the Truffle framework, so the code is extremely high level compared to traditional VM code. Details like how exactly transitions between the interpreter/compiled code happen, how you communicate pointer maps to the GC and so on are all abstracted away. You don't even have to invoke the JIT compiler manually, that's done for you too. The only code Espresso really needs is that which defines the semantics of the Java bytecode language and associated tools like the JDWP debugger protocol.
https://github.com/oracle/graal/tree/master/espresso
This design makes it easy to experiment with new VM features that would be too difficult or expensive to implement otherwise. For example it implements full hotswap capability that lets you arbitrarily redefine code and data on the fly. Espresso can also fully self-host recursively without limit, meaning you can achieve something like what's described in the paper by running Espresso on top of Espresso.
Here it seems this is happening at run-time by using an interpreted language.
Nevertheless the reasoning they give is similar to why you'd want compile-time to be programmable, that the distinction between compiler and program is somewhat artificial and generally severely hobbles the programmer from being able to introspect their program (etc.).
Given how Jai/Zig/etc. work, it now seems crazy that compiler authors have gone to extreme lengths to provide really-bad compile-time languages (called "type systems") that do 5% of what's useful with incomprehensible syntax, rather than just make the compiler itself programmable.
This technique makes much of programming language design seem to be fumbling around in the dark.
Because some things aren't knowable at compile time. E.g. what is the value I enter at runtime, and all values derived from it, but also state of environment, and so on.
Pretending they are the same is a weak point of Zig. By making `const` a property determined by the compiler, you can accidentally introduce breaking changes, just by changing function contents.
I think the key feature here is making compilation a program that you write wherein you can fully introspect your program. Worries here about IDE support fadeaway, as the full state of the compiler is available -- if some annotations on code are required to guide IDEs, so be it.
I wasnt saying that type systems should be replaced with compile-time programs, only that they are compile time programs, and often really bad ones. (My claim: Programmers shouldnt only have the type system to program the compiler.)
Better that the type system be extremely simple and let the programer transform their program as they wish.
Separation of compile vs runtime is as useful as separations between pure and non-pure functions. Pretending they are the same will lose you information.
Sounds to me you just want Lisp or Smalltalk (self modifications galore, no difference between compile and runtime, small syntax).
Compilation is something that happens (generally) once and returns an executable artifact.
Runtime is execution of said artifact, and can happen many times, with many different environment setups.
Compile time functions and types capture stuff that can be known during compilation.
https://3fx.ch/typing-is-hard.html ; more people should understand Hindley-Milner.
Now, there's also a case for compile-time programmability, but that is a feature that needs to be used carefully because it can make the question of what code is actually running very opaque, as well as arbitrarily increasing compile time. (C++, the bad bits)
> making compilation a program that you write wherein you can fully introspect your program
I'm experimenting with C# source generators at the moment, and wondering if there are any breakthrough features we could add this way by making it fully generalizable. (They have the limitation that they are additive-only, you can't mutate existing source)
.Net has System.CodeDom which can load existing source code and mutate it.
I've never heard the term "Live Metacircular Runtimes (LMRs)" but they seem to think they are improving on "classic metacircular approaches"