Close

Entry 10: We Have the Technology

A project log for Lua2e

LUA before Lua: a self-hosting compiler on the Apple //e

jorj-bauerJorj Bauer • 09/29/2026 at 02:37•0 Comments

Ms. Albright pushed this fairly far, from 1984 to 1987, when her drive apparently suffered some catastrophic corruption. In the state I found in my imaging, the boot block was trashed; the directory structure corrupted; some file content lost. I may some day recover more from this beast - I suspect there's a UCSD pascal partition buried in here, which was a common pattern at the time - but, for now, this is where her story wraps up and mine really begins.

In 1987, Ms. Albright measured her LUA against UCSD Pascal. She found hers to be slightly slower, and re-optimized the same way that Apple Pascal did: wrote a 65C02 update to make the code smaller and more efficient, and then tested again.

From my own measurements, the jump to 65C02 is worth 23 percent. Apple shipped Pascal 1.3 in 1986 with an interpreter that checked for the new chip and used its instructions. The same trick applies here: replace that if/else dispatch ladder with a singleJMP (OPTAB,X) through a table of addresses, drop the LDY #0 from LDA (ptr), use STZ. Measured at 1 MHz on the same benchmark, 213 million cycles down to 164 million, with no bytecode changes at all.


Before her final rung, 
her benchmarks show that she just couldn't compete with Pascal's performance, which is a shame (the p-System is, fundamentally, a pig).


These are my timings from her matched programs, same //e, cycle counts from an emulator:

              p-System      hers
LOOP        46,184,684    86,305,138
FIB         36,378,393    47,405,466
ARRAY       80,615,362   265,051,888
SORT       158,549,605   365,241,720

Roughly twice as slow. Reading the dispatch against the handler source tells us why, and it's not really interesting (or surprising); her machine calls a subroutine to take values off of the stack; another one to put a value back; and performs the same operation 13 times to walk a loop once.

All of which she dealt with in her final rung, and once I understood her motivation, I can see the excitement that must have been in her eyes.

She made three fundamental changes, all of which are invisible to the coder in LUA:

  1. Guess that a table, being used is an array, is indeed an array;
  2. Unroll the callouts for push/pop to make the code slightly bigger, but more efficient;
  3. Fuse 6 common sequences into single VM instructions.

Her result is 2.42x faster after these, which lands it 17% faster than p-code; and with the 65C02 changes she made after, it is a whopping 30% faster.

              p-System      rung 12
LOOP        46,184,684    33,995,771
FIB         36,378,393    34,106,801
ARRAY       80,615,362    65,538,571
SORT       158,549,605   151,591,612

 
Looking at the historical path for Lua, and comparing it to what Ms. Albright's LUA did: Lua had the same challenge. With Lua 5.0, the stack machine was replaced with a register machine - buying the same savings by changing how operands are addressed rather than by fusing pairs. Same diagnosis; opposite prescription. And 16 years apart.

Discussions