Another way (How not to write a loop)
Jerry Leichter
leichter at yale.UUCP
Sat Feb 20 04:43:00 AEST 1988
Commenting about the inplementation of SPITBOL/360, which used a floating
point register to keep track of the number of statements executed, Doug
Gwyn writes:
>
>So, the Snobol implementor made a stupid decision, then.
>
He the proceeds to explain that the decision was stupid (a) because when he
compared two ways of doing this on a Gould Powernode, doing it with integers
was faster; (b) the way SPITBOL did it was "non-portable".
It's generally a good idea to understand the issues before criticizing a
design decision. Neither Doug's comments, nor any of the others on this
topic, are based on any such understanding. They appear to be made by people
who don't understand the language, the implementation environment, the goals
of the implementation --- the probably don't even know to within 5 years
when the implementation they are criticising was done. How anyone can have
the chutzpa to imagine that they have ANYTHING worthwhile to say, lacking all
that basic information, would be beyond me if I hadn't seen so much flammage
on this net already.
To add a little reality: SPITBOL/360 was done somewhere around 1971. It was
an attempt to produce a complete implementation of all of SNOBOL4 that would
run as fast as possible. There was already a very portable --- certainly by
the standards of the late 1960's, probably even by today's standards --- im-
plementation of SNOBOL in existence. It took, by the standards of the day,
a huge amount of memory, and ran slowly. SPITBOL attempted to address both
constraints. It was willing to forgo portability, and was designed to run
on IBM/360's --- yes, 360's, the 370 wasn't to exist for several more years ---
under OS/360.
Now, SNOBOL4 is not an easy language to execute efficiently. It allows for
things like the creation of new functions, data types, and even variables at
run time --- and these abilities are heavily used. It allows new code to be
compiled at run time, sometimes replacing existing code. Assignments to, or
even attempts to read from, variables can trigger I/O, or (via tracing) the
execution of arbitrary user code. The fact that a particular access to a
particular variable may have such affects can only be determined at run time.
Enough generalities. The particulars of the use of a floating point statement
counter are as follows: Floating point arithmetic is quite rare in SNOBOL
programs, so there is little to be gained by keeping FP registers --- and
remember, on a 360 FP registers are completely distinct from the general
registers --- free. On the other hand, the nature of SNOBOL, and the way
addressing works on a 360, places a premium on general registers. Also, in
the early '70's, core was CORE --- registers were MUCH faster than main
memory. Even FP registers and FP operations were quite fast compared to
main memory accesses.
Now, SNOBOL numbers statements, and it counts statements executed. The
statement count must be checked at the beginning of every statement executed
against a (user-changable, at run time) statement limit. The statement number,
on the other hand, is only used in rare circumstances --- in generating errors,
or in the (in practice) unlikely event that the user asks for it. So the
SPITBOL implementors did something clever: They used an otherwise-unneeded
resource (an FP register) in a clever way to solve several problems. The
counter was kept in the FP register, and the hardware effectively did the
statement limit check. Meanwhile, the actual instruction used --- an AUR,
as Rahul Dhesi noted, Add Unnormalized Register --- was "unusual"; in fact,
it was never generated by the compiler anywhere but at the head of a statement.
Thus, it acted as a "statement begin" marker. No record was kept of the
current statement number --- doing that would have required tying up another
register, or an extra memory access, at each statement. Instead, on the rare
occassions that the current statement number was needed, the run-time code
would walk through all the compiled code --- it was all linked together ---
and count AUR's until it got to the currently-executing statement.
I believe there may have been other instances in which it was necessary to
find the beginning of the current, or the next, statement; searching for an
AUR could be used for that, too.
All told, an elegant, effective, and fast solution, given the realities of
the day.
Some of the same people who design SPITBOL/360 later went on to develop
MACRO/SPITBOL, a rather interesting implementation that was designed to be
(a) portable; (b) efficient on any particular hardware. It succeeded;
MACRO/SPITBOL on a PDP-10 was smaller, and usually faster, than SITBOL, an
implementation that had been hand-tuned for the -10. MACRO/SPITBOL, now at
least 10 years old, continues to be available; it runs on such machines as
VAXes and 8086's, both designed well after the implementation.
-- Jerry
More information about the Comp.lang.c
mailing list