Y'know, after the addition of the capabilities instructions and the various complexities of the OotB? i think OotB? is just getting too complicated. It's no longer an 'implement this on your platform in one afternoon' kind of thing.
So let's subset it yet again. SootB? is a simple stack-machine subset of OotB?.
---
note that OotB? is also rotated "Boot", which is appropriate.
---
we should have a compiler from OotB? to SootB?, not just an interpreter.
---
The need for SootB? calls into question the value of OotB? at all (as more than an implementation detail). If we are already compiling Oot Core into OotB?, and OotB? into SootB?, then why not just compile Oot Core into SootB?? Recall that two of the main motivations for a separate OotB? were (a) to make it dead easy to bootstrap on a new platform, (b) to have a separate layer of services (like GC, greenthreads, etc) underneath Oot Core. (and of course there's also the motivations of execution via a bytecode interpreter runtime, and having a platform-independent pre-compiled object format for storage of code, but these things are implementation details).
But now we have SootB?. And some non-trivial OotB? services (eg capabilities; forking) are being implemented in SootB?.
If we have SootB? then there's (a) already. As for (b), why not just implement the services themselves in Oot Core and then compile them from Oot Core directly into SootB?? Perhaps this compiliation might pass through OotB? as an implementation detail, perhaps not.
This would require Oot Core having a subset and a 'mode' in which the services are not relied upon. That seems doable. Like RPython; exceptions actually act differently in Python and in RPython (in some cases, in RPython, an exception is simply not generated at all if there is no exception handler matching it).
OotB? might still exist (as an implementation detail in the compiler from restricted Oot Core and SootB?, and in the module file format), and thinking about it in detail will still inform the semantics of this Oot Core 'mode'. But it may not be something that either Oot users or porters have to think about.
This is disappointing to me because i've developed an affection for OotB?. But at the same time i have been feeling that i've been placing too much importance onto what should be implementation details, and premature optimization. How many addressing modes should OotB? really have? Should it have indirect offset? Should it have indirect, or instead have LOAD/STORE? I dunno, that stuff is an optimization. Also, i feel that having three layers (OotB?, Oot Core, Oot) is already pushing it, and having 4 layers is too much (as an implementation detail that would be fine, just not as part of the main design).
So if i decide that what i've written above is correct, then maybe OotB? is dead. But it will live on in the form of a fairly close mapping between restricted Oot Core, and OotB?, at least initially.
There are three hitches.
First, some of these services (like capabilities and greenthreads) really do seem like they have to run 'beneath' ordinary Oot Core. If the non-primitive 'custom functions' in the OotB? stdlib are to be written in a manner oblivious to capabilities and greenthreads, then these implementations may have to run 'on top of' a lower-level execution environment. Perhaps we could come up with some metaprogrammy stuff in Oot Core to express this?
Second, a huge benefit of OotB? was the incrementality of porting. The porter initially only has to implement the primitives, and then they can add in platform-native implementations of the stdlib custom instructions one by one, and see an increase in execution speed each time they do so. We would want to preserve this if we switch to Restricted Oot Core, perhaps by having an FFI and exposing an interface where the porter can register a native function as replacing a library function; but note that we want to be able to INLINE the custom instructions. In addition, perhaps the implemention of some custom instructions is best done by changing the interpreter in a way more globally than can be expressed by giving a single function to be inlined. Again, perhaps we could come up with some metaprogrammy stuff to express this in Oot Core. We don't want to tell the porter that they have to write an entire parser for Restricted Oot Core before they can start replacing the custom instructions with platform-native implementations; that's one of the issues i have with an RPython approach.
Third, what if we want part of Core Oot to not be very imperative, like eg F-lite or Reduceron Template Language?
---
fantom:
" We built Fantom from the ground up to tackle portability between these VMs. Fantom's source language compiles into fcode - a bytecode representation that can be translated into both Java bytecode and IL easily. This translation is typically done at runtime, which enables you to deploy Fantom modules as a single file and have them run on either VM.
But getting a language to run on both Java and .NET is the easy part - in fact there are many solutions to this problem. The hard part is getting portable APIs. Fantom provides a set of APIs which abstract away the Java and .NET APIs. We actually consider this one of Fantom's primary benefits, because it gives us a chance to develop a suite of system APIs that are elegant and easy to use compared to the Java and .NET counter parts. "
---
i dunno, maybe having Oot Core (and maybe even Root Core) and OotB? and SootB? is okay. They do each seem to serve a function:
GHC has a buncha steps:
Haskell AST -> Core -> STG -> (C--/Cmm or LLVM or native code)
Clearly, Haskell ~= Oot, GHC Core ~= Oot Core, LLVM ~= SootB?. STG is either ~= Root Core or ~= OotB?. Cmm is somewhat like OotB? but not entirely b/c i think Cmm already provides lots of services.
Root Core is like RPython. OotB? is also like Parrot or perhaps Parrot M0.
OotB?/Root Core is like Shen KLambda (Kl)
Could just combine OotB? and SootB?. This is what i was originally thinking, but OotB? is ballooning, esp. with capabilities and the module loading file format.
---
look, if OotB? made interoperability better it would totally be worth it, but who knows if it actually will?
---
again, just go with LLVM instead of SootB?? No, too hard to port: http://llvm.org/docs/WritingAnLLVMBackend.html
WebAssembly?? Maybe, but again, probably too hard: https://webassembly.github.io/
KLambda? Probably too hard: http://shenlanguage.org/Documentation/shendoc.htm#Kl
---
ELF program header types:
" The type may be one of the following. The numbers indicate the value of the keyword.
PT_NULL (0) Indicates an unused program header. PT_LOAD (1) Indicates that this program header describes a segment to be loaded from the file. PT_DYNAMIC (2) Indicates a segment where dynamic linking information can be found. PT_INTERP (3) Indicates a segment where the name of the program interpreter may be found. PT_NOTE (4) Indicates a segment holding note information. PT_SHLIB (5) A reserved program header type, defined but not specified by the ELF ABI. PT_PHDR (6) Indicates a segment where the program headers may be found. expression An expression giving the numeric type of the program header. This may be used for types not defined above. " -- http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_23.html
" 0=NULL Null segment (optional)
1=LOAD Loadable segment (code, data, bss, etc.)
2=DYNAMIC Dynamic linking information
3=INTERP Path to dynamic linker, e.g. /lib/ld.so
4=NOTE OS-defined
5=SHLIB Reserved. DO NOT USE.
6=PHDR The program header table itself" -- http://geezer.osdevbrasil.net/osd/exec/elf.txt
---
" I don't mean to imply that there are no new instructions that will ever need to be added! I think popcount is an example that is very painful to handle in software, and the idiom in assembly is probably too big to handle via macro-op fusion. I'm also very excited to eventually have a vector ISA in RISC-V.
Rather, my abstract is fighting against a whole slew of instructions that exist in current ISAs (or that people want to add to RISC-V) that don't need to be there. The load-pair/load-increment types that you see in ARMv8 come to mind. "
cperciva 35 days ago [-]
Can you recognize and automatically perform macro-op fusion on AES computations? How about SHA256? Ok, let's make it easy -- CRC32?
"saturating adds and multiplies that came with the DSP requirements, or the SIMD extensions that came with graphics"
---
Taniwha 35 days ago [-]
The thing is the base x86 architecture ISNT very CISCy, there's only simple addressing modes (no double indirect modes), no addressing side effects to undo on exceptions (auto increments), only one TLB dip per instruction
(the push instruction is really the only excepetion)
compared to its compatriots (68k/vax/NSwhatever etc) it was positively RISCy in comparison - a vax instruction could take something like 29 TLB misses, make 29 memory accesses - a 68020 threw a horrible mess of microstate spew on a TLB miss so it could make progress (made unix signals implementation a nightmare, where do you safely put that stuff?)
---
i guess there's no real reason that SootB? would need to be a subset of OotB?. Except that it encourages people to go ahead and extend their shiny new SootB? implementation into a full OotB? implementation. Which is a good reason.
But... there are less than 16 core instructions. Which means.. if we were willing to make LOADK and J consume two instruction fields (be variable length).. we could have 2 instructions per byte! That's 16 per 64 bits, ~twice as many as our SHORT encoding in OotB?, and less complicated.
---
And what if we just threw out OotB? and only had SootB?, Root Core, Oot Core, and Oot?
I guess it depends on if OotB? really makes interoperability any easier, or if the implementors can plug into Oot Core and Root Core just as easily.
We'd still need some sort of Root Core and/or Oot Core bytecode serialization, i guess, which may well end up looking a lot like OotB?.. but that would then be an implementation detail.
I feel a little bad about abandoning OotB? after i've grown to like it, but hey, you gotta do what you gotta do. And, as i've said, OotB?