Self
Self is a prototype-based, dynamically typed object-oriented language and live programming environment created by David Ungar and Randall B. Smith in 1986-87, whose classless object model shaped JavaScript and NewtonScript and whose adaptive-optimizing virtual machine became the direct ancestor of Java's HotSpot JIT
Created by David Ungar and Randall B. Smith, who designed the language at Xerox PARC in 1986; implementations and the graphical environment were built at Stanford University by Craig Chambers, Urs Hölzle, Ole Agesen, Elgin Lee, Bay-Wei Chang and Ungar, and continued at Sun Microsystems Laboratories with Smith, Mario Wolczko, John Maloney and Lars Bak
Self is a prototype-based, dynamically typed object-oriented programming language, together with a live graphical programming environment and a virtual machine, built around four stated principles: simplicity, uniformity, concreteness and liveness. It began in 1986 as an attempt to find out what was left of object-oriented programming if you took classes away, and ended up producing two separate legacies far larger than the language itself - the prototype object model that JavaScript uses in every browser, and the adaptive just-in-time compilation technology that became Java’s HotSpot VM.
History and origins
David Ungar and Randall B. Smith designed the first version of Self in 1986 at Xerox PARC. Smalltalk-80 had just been released from the lab into the wider world and was starting to be taken seriously by industry; the question Ungar and Smith set themselves was whether the state of the art could be pushed further by making the object model simpler rather than richer. Their answer, presented as “Self: The Power of Simplicity” at OOPSLA ‘87 in Orlando in October 1987, was to collapse three distinctions at once: classes versus instances, variables versus procedures, and state versus behaviour.
Ungar moved to Stanford University, where the first working Self compiler was built in 1987 and a series of implementations followed, produced by Craig Chambers, Urs Hölzle, Ole Agesen, Elgin Lee, Bay-Wei Chang and Ungar. The first public release, Self 1.0, was distributed free of charge by anonymous FTP from self.stanford.edu in 1990 for Sun-3 and Sun-4 workstations; the self-interest mailing list was already carrying user questions by late July of that year. Self 1.1 followed on 31 January 1991.
The project then moved to Sun Microsystems Laboratories, jointly led there by Smith and Ungar and joined by Mario Wolczko, John Maloney and Lars Bak. Release 2.0 (10 August 1992) was the first to ship complete, legally unencumbered source code. Release 3.0 (23 December 1993) made the graphical environment fully self-sufficient - all programming tasks could finally be performed through the UI - and introduced the transporter, a mechanism for saving arbitrary object graphs back out as Self source, which is how an image-based system keeps a version-controllable source tree.
Self 4.0, released in July 1995, was the last release of the original project and the one people remember. It replaced the interface wholesale with Morphic, added the shared two-dimensional Kansas desktop on which several users could work simultaneously with their own cursors, and threw in a web browser and a Smalltalk emulator written in Self. Work on the project at Sun officially ceased that same year.
Self did not stay dead. Ungar restarted it as a spare-time Mac OS X port in 2001 (4.1.4, 7 August), and a series of releases ran through 4.1.5 and 4.1.6 (2002), 4.2 (20 June 2003), 4.2.1 (16 April 2004) and 4.3 (30 June 2006), the last adding an x86 port for the new Intel Macs. In October 2008 Russell Allen imported the CVS tree into a public GitHub repository, and maintenance has been community-driven ever since: 4.4 in 2010 (the first Linux release), 4.5.0 “Mallard” in 2014, 2017.1 “Mandarin” in 2017, and 2024.1 in August 2024.
Design philosophy
Self’s design is an argument that a class-based language carries two object systems where one will do. In Smalltalk you have objects, and you have classes, which are also objects, and metaclasses, which are also objects; in Self there are only objects.
Every Self object is a collection of slots. A slot has a name and holds a value. That is the whole data model - there is no separate notion of an instance variable versus a method, because a method is just a slot whose value happens to be executable. Reading a slot and calling a method are the same operation: sending a message.
| |
New objects are made by cloning an existing one, not by instantiating a class. An object used mainly as a template for cloning is called a prototype, but it is not special in any way - it is a perfectly ordinary, fully functional object that happens to be the one everybody copies.
Sharing comes from delegation. Any slot whose name ends in an asterisk is a parent slot; a message an object cannot handle itself is forwarded to its parents. Because a parent slot is a slot like any other, it can be assigned at run time:
| |
which is roughly the equivalent of changing an object’s class while it runs. The Self team showed in “Organizing Programs Without Classes” (Ungar, Chambers, Chang and Hölzle) that everything classes are conventionally used for - shared behaviour, namespaces, behavioural modes, even class-style encapsulation - falls out of plain object inheritance without special mechanism. The idiom that replaced classes in practice is the traits object: a shared parent holding only the methods, with the cloned prototype holding only the data.
The syntax is Smalltalk’s, with unary, binary and keyword messages. Because so many messages are sent to the receiver itself and the receiver may be elided, the language is named for the word you keep not having to type.
The virtual machine: where the real influence lies
Removing classes and explicit variables made Self radically harder to compile well, and the effort to do it anyway produced most of the techniques that modern dynamic-language runtimes are built from.
| Technique | Introduced in | What it does |
|---|---|---|
| Maps | Chambers, Ungar & Lee, OOPSLA ‘89 | A hidden, shared, implementation-level descriptor grouping objects cloned from the same prototype, recovering the type information a class would have given the compiler and removing the apparent space cost of prototypes |
| Customization | Chambers & Ungar, PLDI ‘89 | Compiling a separate machine-code version of a method per receiver map, so that sends to self can be statically bound and inlined |
| Polymorphic inline caches | Hölzle, Chambers & Ungar, ECOOP ‘91 | Caching several lookup results per call site, and - as a side effect - recording every receiver type actually seen there |
| Dynamic deoptimization | Hölzle, Chambers & Ungar, PLDI ‘92 | Reconstructing un-optimized stack frames on demand so a debugger can show expected source-level behaviour in globally optimized code |
| Type feedback / adaptive recompilation | Hölzle & Ungar, PLDI ‘94 and OOPSLA ‘94 | Feeding the recorded receiver types back into a recompiling optimizer, so hot code gets optimized and cold code does not |
The measured results were not marginal. The 1989 OOPSLA paper reported the Self implementation running about twice as fast as the fastest Smalltalk implementation of the day on the authors’ benchmarks. Polymorphic inline caches gave a median 11 percent speedup on a set of typical Self programs, rising to 27 percent in an experimental recompiling version that exploited the collected type data. Type feedback cut the frequency of non-inlined calls across a suite of large Self applications by a factor of 3.6 and improved their performance by a factor of 1.7. The Self-93 system described at OOPSLA ‘94 ran two to three times faster than existing Smalltalk systems while keeping compilation pauses short enough for interactive use - the first pure object-oriented implementation, its authors argued, to get both at once. Later summaries of the work, including Ole Agesen’s 1997 paper on the Pep Java translator, put well-optimized Self at roughly half the speed of optimized C on some benchmarks; the exact figure depends entirely on which benchmarks, and the Self papers themselves are careful to report per-benchmark results rather than a single number.
Memory management used generational garbage collection, segregating objects by age and using the memory system’s page-write records to maintain a write barrier cheaply.
The path from this work to industry is unusually direct. In 1994, as the Self project wound down, Lars Bak left Sun and joined David Griswold and Urs Hölzle - the author of much of the Self compiler, by then at UC Santa Barbara - to found Longview Technologies, trading as Animorphic Systems, where they built the Strongtalk Smalltalk system on the Self VM’s type-feedback design. Sun bought the company in February 1997, pointed the team at Java, and shipped the result as the Java HotSpot Performance Engine on 27 April 1999. HotSpot’s name describes the same behaviour Self’s VM had: watch the program run, find the hot spots, optimize those.
The environment
Self is not a language you compile files with; it is a world you live inside. A running system is a snapshot - a saved memory image of every object, including the programming tools themselves - and programs are shipped as snapshots rather than as standalone executables. Debugging a snapshot is easier than debugging a conventional program because the entire run-time state is there to inspect and change; the cost is that images are large and unwieldy.
The 4.0 environment introduced Morphic, built by John Maloney and Randall B. Smith and presented at UIST ‘95. Its two design goals were directness - you examine or change a UI component by pointing at the thing on screen, not at a description of it elsewhere - and liveness - the interface never stops running, so animation, layout and displays keep updating while you edit. Objects are presented as outliners, expandable views that let you see as much or as little detail as you want, with a graphical debugger and navigation tools alongside. Refactoring is done by dragging methods between objects.
The other 4.0 novelty was Kansas: any Self window is a movable frame onto one vast shared two-dimensional plane, so several users on a network can bring their frames together to manipulate the same objects, each with their own cursor, then move apart to work independently.
Current status
The original research project ended in 1995, and Self’s status as a language has been essentially frozen since - the interesting work moved into its descendants. But the system is not abandonware. The GitHub repository at russellallen/self has seen commits in every year since 2008, including active work through 2026 from maintainer Russell Allen and occasional commits from David Ungar himself, with recent effort going into 64-bit safety, Clang compatibility, Kansas navigation and reviving builds on older macOS.
Per the current Self Handbook, Self is distributed for Linux, FreeBSD and NetBSD on x86 under a BSD-like licence. The macOS port was deprecated in the 2024.1 release, having been broken since macOS Catalina dropped 32-bit support in 2019. Historically the system ran on SPARC under SunOS 4.1.x and Solaris, and later on PowerPC and Intel Mac OS X. There is no official Docker image.
Self’s own research lineage continued past the language, too: the Klein metacircular VM (2006), and Smith and Ungar’s later work on subjective programming - “Us” (1996) and Korz (Onward! 2014) - which asks what happens when an object’s behaviour depends on the context doing the asking.
Why it matters
Self is the clearest case in language history of a research system whose ideas are ubiquitous while the system itself is unknown. Two of them in particular:
The object model won. Prototypes, delegation and slot-based objects went from Self into NewtonScript on the Apple Newton, and from that lineage into JavaScript. Every web page in the world runs on Self’s answer to “what if there were no classes?”, even though almost nobody writing that code has heard of Self - and the subsequent addition of class syntax to JavaScript is sugar over the delegation model Ungar and Smith built.
The implementation techniques won. Maps became hidden classes in V8. Polymorphic inline caches, type feedback, tiered compilation and dynamic deoptimization are the standard architecture of HotSpot, V8, SpiderMonkey and essentially every serious dynamic-language JIT since. Lars Bak, who worked on the Self VM at Sun, later led both HotSpot and V8.
The environment did not win, and that is the interesting part. Morphic’s directness and liveness, live editing of a running world, objects you manipulate rather than describe - these survive in Squeak, Pharo and Scratch but never displaced the edit-compile-run file-based workflow. Self remains the most complete demonstration of the alternative, which is why it is still worth running: not to ship anything in it, but to see what a programming system looks like when nothing between you and the objects is allowed to get in the way.
Timeline
Notable Uses & Legacy
Java HotSpot virtual machine
HotSpot descends directly from Self. David Griswold, Urs Hölzle - who had built much of the Self compiler at Stanford - and Lars Bak, who had worked on the Self VM at Sun, founded Longview Technologies (trading as Animorphic Systems) in 1994 and built the Strongtalk Smalltalk VM there on the Self VM's type-feedback design; Sun bought the company in February 1997 and shipped the retargeted result as the Java HotSpot Performance Engine on 27 April 1999. Self's inline caches, type feedback, adaptive recompilation and dynamic deoptimization are the ancestors of the techniques every modern JVM uses
Morphic, and its descendants in Squeak, Pharo and Scratch
John Maloney and Randall B. Smith built the Morphic user-interface construction environment for Self 4.0, aiming at "directness and liveness" - editing live interface components by pointing at them. Morphic was subsequently ported to Squeak Smalltalk, where it became the standard UI framework carried on into Pharo, and it underpins the block-dragging interface of the Squeak-based Scratch environment
NewtonScript on the Apple Newton
Walter R. Smith's team at Apple studied Self closely while designing the language for the Newton MessagePad. NewtonScript keeps Self's prototype-and-slot object model but adds a second inheritance axis for GUI layout and a far smaller memory footprint: a typical Self snapshot of the era is reported to have needed around 32 MB of RAM, while the Newton platform was designed to give its operating system roughly 128 KB
JavaScript's object model
JavaScript's classless, prototype-based objects - where an object delegates to another object rather than instantiating a class - come from the Self and NewtonScript lineage rather than from Smalltalk or Java, making Self's object model the one that ended up running in every web browser
Klein, a metacircular Self virtual machine
Adam Spitz, Alex Ausch and David Ungar built Klein at Sun Labs as a Self virtual machine written entirely in Self, so that the whole system down to the VM could be inspected and changed live from within the environment; version 0.1 was released on 14 August 2006 under a BSD licence
Smalltalk hosted on the Self VM
Self 4.0 shipped a Smalltalk system built from the GNU Smalltalk class library, a Smalltalk-to-Self translator and a Smalltalk user interface. Mario Wolczko, who described the work as "self includes: Smalltalk" at the ECOOP '96 prototype-based languages workshop, benchmarked it against ParcPlace ObjectWorks/Smalltalk 4.1 on the same Sun SPARCstation-10, taking the best of 20 runs on three medium-sized non-graphical benchmarks (Richards, DeltaBlue in two configurations, and Diff): the Self-hosted Smalltalk was faster on all four measurements, by factors ranging from 1.1 on Diff to 2.7 on Richards. Wolczko cautioned that the DeltaBlue and Diff comparisons are muddied by differences between the GNU and ParcPlace collection classes