HIGH and LOW
Jecel Assumpcao Jr
jecel@lsi.usp.br
Thu, 11 Apr 1996 23:42:56 -0300
Lewis Carrol's Alice said "How can one possibly pay
attention to a book with no pictures in it?". If we could
look at a drawing of the Tunes architecture, maybe there
would be less confusion.
Merlin is even worse, of course, since its pages have
pictures that are actually misleading (a trait it sadly
shares with Sony's Apertos papers). On the other hand,
I have a good picture of it in my head and everyone
involved in the project (me, myself and I ;-) more or
less agrees with it.
Unfortunately, email is not the best medium for figures
(and I am not good with ASCII art) so I will try to show
my views of high level and low level things with words
only.
I actually see three different level separations that
might be made.
1. base semantics VS minimum semantics
======================================
The base semantics (BS) is what every program can count on.
If you build that from a smaller minimum semantics (MS), you
get a system that is much easier to port. You only have
to rewrite the MS to have to whole system running on another
machine. It is also easier to find a simple platform
independent coding for the MS (like the Java bytecodes).
An example of this is Mario Wolczko's Smalltalk emulator
for Self. Here the BS includes classes, several different
scopes of variables, a large library, etc. Self only
provides objects and slots as the MS, so that is all
that has to be reimplemented in another machine to have
the whole thing working.
The relation between the HLL and Scheme might be
something like this.
2. user built VS primitives
===========================
Extendable systems can't be built out of thin air. So we
need a set of primitives to start things off. Here, the
user built level "escapes" into the primitive level rather
than being a simple extension of it. So the primitive might
be a library of functions written in another language
(see how most C compilers handle A*B, for example) or it
might be implemented as an "idiom" recognized and especially
treated by a compiler (like C does with A+B).
Portability is again an issue, here. The less that is done
as primitives, the easier it is to get the system running
on another platform, but the system will make less use of
that platform's unique qualities. If you build an int2float
operation from basic instructions, for example, you will
miss a chance to generate good code on CPUs that have this
as a single instruction. If you do 3D graphics "by hand"
in your application, putting a hardware accelerator won't
help at all.
This is a hard problem, much like having compilers use
complex instruction in CISC chips. If you get this wrong,
a combination of code inlining and very smart idiom
recognition might save you later, but it isn't very
likely.
3. application VS implementation
================================
An application does what the user wants. The implementation
is all the details needed to make it work. I would say
that the better these two things are separated, the higher
is the software's quality. The worst thing is to mix them
up.
Let's say you have a spreadsheet on a Amiga. Some parts
of that machine's RAM is slower than the rest. But it
does some things the rest can't (like hold a sprite). If
you can separate this into a different level (or API,
or whatever) then it would be easy to change that part
to deal with the Transputer, or a Pentium with an old
ISA memory board, or a totally new NUMA architecture.
On the other hand, a good piece of code to handle
Amiga's quirks might be used for many different
applications. So this separation makes each part
more reusable.
There is a level of code that should be communication
protocol independent. And a level that has to deal
with the details. A level that is storage system
independent, and a level that is not. A clean interface
between them is the most important aspect of an OS
design.
And here is where garbage collection comes in. If you
don't have it, the application code will end up mixed
with memory management code (most people don't even
notice it because they think memory management *is* part
of the application logic!). A GC lets the two levels
be clearly separated. For more about GC you should
look at Paul Wilson's survey at
http://www.cs.utexas.edu/users/oops/
I had to come up with four separate solutions to
these three issues (two for primitives) in Merlin.
The HLL and LLL thing in Tunes is probably related to
this (though there might be more issues I haven't
considered). Anyway, I hope this starts to clear up
why all the discussions we have been having lately
were unavoidable. There is more than one aspect to
this problem and different people have been talking
about different things.
-- Jecel Mattos de Assumpcao Jr
Laboratorio de Sistemas Integraveis
University of Sao Paulo - Brazil
mailto:jecel@lsi.usp.br
http://www.lsi.usp.br/~jecel/merlin.html