Of course an MMU and/or lots of RAM does make multitasking a lot easier.
OS-9 is an awesome UNIX-like for the 6809 that can do it in 64K or less.
Of course an MMU and/or lots of RAM does make multitasking a lot easier.
OS-9 is an awesome UNIX-like for the 6809 that can do it in 64K or less.
Can you clarify what kind of penalty it had then?
Such languages would be pretty painful on another architecture implemented as interpreters. I don't have exact numbers. But roughly an order of magnitude slower. Think Perl and Python vs. Pascal and C.
Things have changed a bit since then. Oberon is usually compiled to native code now and Squeak uses a JIT compiler. And Mesa/Cedar are extinct.
To quibble about one more thing, multitasking doesn't increase memory requirements significantly on anything big enough to run an interpreter. On this amd64 machine under Linux, sizeof(jmp_buf) is 200 bytes; that's how much space each new task would needs, plus of course the size of its stack. If I build for i386, it's 156 bytes. But of course you can define the calling convention to reduce this: on 16-bit Forth systems a suspended (cooperative!) thread was typically a data stack pointer, a return stack pointer: 4 bytes. (But typically each thread had its own dictionary of at least 4K.) Preemptive multitasking generally requires at least the size of the register file, since you can't discard caller-save registers on every context switch.
What does increase memory requirements enormously is memory protection — not mere multitasking but allocating exclusive segments or pages to each new program. That's a big part of the appeal of systems like Oberon, Smalltalk-80, and of course early Oak/Java: by implementing memory protection at the language level rather than the hardware level, you could get very fine-grained memory sharing without endangering system stability.
[0]: https://www.microsoft.com/en-us/research/wp-content/uploads/...
Edit: Fine, I'll put the link in a footnote.
Those architectures are just so painful for generating reasonable code, mostly with regards to size, that a clean 16 bit VM starts looking attractive. Memory use is often more critical than speed on an 8-bitter, and for large applications even with the interpreter the bytecode is almost always smaller.
And if you're doing a full VM, it's not too painful to add a memory protection check. One can sustain about 5 - 10K virtual instructions a second on a 6502 @ 1 MHz.
As insanely inefficient as this all sounds, it was actually done back in the day. One notable example would be the old Business Operating System which was basically a bytecode interpreter glued to a small multitasking operating system. All the compilers and applications and most of the OS itself ran in interpreted bytecode.
Java, Python, Perl, Ruby, and a host of others say this isn't a dead technique.
Another reason for it back then was to only need to port the interpreter to each different architecture and platform, an important consideration in the 80s with the bloom of CPUs and machines.
However, either way, hardware memory protection adds another layer of safety/security, just like the no-execute (NX) bit. It makes it harder for attackers to hijack your VM, and also less likely that a program, because of a bug in your VM, could crash other processes or even the kernel.
IBM mainframes still do on their classical mode, the bytecode gets AOT compiled at installation time, or when the binaries need to be refreshed due to changes on the hardware.
Burroughs B5500, nowadays still sold by Unisys as ClearPath MCP, was already doing this in 1961.
I suspect in this comment you are confusing IBM i and its predecessors (i5, AS/400, System/38) with IBM mainframes (z, 390, 370, 360). The former do what you are talking about, the later don't. In proper IBM terminology, the former are called midrange systems, not mainframes.
What are you talking about? When you say "IBM z", which OS are you talking about – z/OS, z/VM, z/VSE, z/TPF or z/Linux?
Which "language environments" are you referring to? Do you mean "z/OS Language Environment"? That doesn't involve "bytecode" in the sense that OPM/EPM/ILE on OS/400 do. LE (on z/OS, z/VM and z/VSE) and ILE (on OS/400) are descendants of the same code base (and I believe that code base was even ported to OS/2 at one point), but ILE on OS/400 does some very OS/400-specific things which never happened on MVS, VM/CMS, DOS/VSE or OS/2.
You started out by saying:
> IBM mainframes still do on their classical mode, the bytecode gets AOT compiled at installation time, or when the binaries need to be refreshed due to changes on the hardware.
That is kind of true for IBM i, but just false for IBM z.
> I call all of them mainframes, instead of precise definitions, because everyone without experience has a vague idea what a mainframe is, whereas midrange systems, most likely requires a Wikipedia visit for most of the audience.
While "midrange" is a bit of an obscure IBMism, most people have heard of "minicomputer", and have the historic understanding of a "minicomputer" as something in between a microcomputer and a mainframe. I think "minicomputer" would be more accurate than "mainframe" when referring to the S/38 and its successors. Calling the later "mainframes" is just going to confuse anyone familiar with the proper IBM terminology.
I get the impression you like to make comments like "IBM did X years before this did" but they make you come across as someone opining on something they don't know a lot about, and you end up saying things which make people who know more about the topic than you do cringe.
For memory protection, you don't need an MMU; an MPU (memory protection unit) suffices:
https://en.wikipedia.org/w/index.php?title=Memory_protection...
Most RTOSes out there work just fine even without MMU or MPU.
It was designed to run on anything from light weight mmu-less bare metal embedded with no graphics to full fledged PC class hardware. It included a hosted mode where the kernel is built as a program that runs on plan 9, unix, unix-likes, and windows. The kernel is a vm with no way to implement native code unless you add it to the kernel.
Since everything runs in the dis vm you can have a truly portable os where the same program that runs on a headless embedded mips box will run unmodified in hosted inferno on an x86 Linux machine. Unfortunately it does not yet run on x86-64 due to dis having hard coded 32bit constraints. However, someone is actively working on that little issue.
A fork that aims to make inferno easier to run out of the box and develop on: https://code.9front.org/hg/purgatorio/
The much-maligned x86 segment registers do come in handy here: they provide hardware-accelerated position independent memory addressing! Most DOS utility programs were small enough to fit in a single 64K segment, and provided they never touched the segment registers, these programs were trivially relocatable to any memory address.