=== Top of the Swiki === Attachments ===
The Squeak Image
NOTE: This page is still under construction
- Dan Ingalls 4/28/99
A Squeak Archaeologist's Tool Kit
Many newcomers to Squeak never quite feel at home in a Squeak image. They are comfortable with programs stored as source code and manipulated through a browser, and with objects stored as structures and viewed through inspectors, but the rest of the Squeak environment remains somewhat of a mystery.
Actually, the structure of a Squeak image is quite simple, and there are many tools available for exploring and manipulating that structure. Moreover there are tools for locating and dealing with even the most perverse misconstructions that can result from errors or other unforseen situations.
The Smalltalk dictionary
There is one key global variable in Squeak, and it is called, for obvious historical reasons, Smalltalk. Smalltalk is a dictionary of all global variables in the Squeak system (including itself), and almost all of these are references to classes. Unless you take special pains to the contrary, defining a new class will cause its name to be entered as a global variable in Smalltalk.
Note that Smalltalk is actually an instance of a subclass of Dictionary called SystemDictionary. It behaves almost exactly the way other dictionaries do, but lots of useful methods are defined in SystemDictionary and can thus be invoked by executing a statment like "Smalltalk,
All globals that are not classes can be enumerated by the do-it in SystemDictionary's class comment (there is one! ;-)...
Smalltalk keys select: [:k | ((Smalltalk at: k) isKindOf: Class) not]
thenCollect: [:k | k -> (Smalltalk at: k) class]
In the Version 2.3 image, this produces a Set containing...
Building images from scratch
If one wanted to build a Smalltalk image starting from only the system sources, one could do so by creating an empty dictionary object, compiling all the classes into it (this would require a pre-existing compiler), and then initializing all the class dictionaries and the global variables above. Most class variable dictionaries get properly initialized by an 'initialize' method, and most of the globals have a method somewhere for creating and initializing them as well. To find these methods, inspect Smalltalk itself, select the global in question, and then invoke the 'references' command from the variable list menu.
The Squeak team never builds a system in this manner because we find it easier to work with a running system all the time. For the very rare cases in which this is not possible (changing the formats in the ObjectMemory, for instance), we use a special tool called the SystemTracer. The SystemTracer builds an image from scratch, but working from an existing system, not from the source code files.
Yet another approach, which we have never explored, would be to build a second global dictionary in a running Squeak, compiling copies of all the classes into it, and then storing it into the specialObjects array (q.v.) just before saving a snapshot.
The Principal Global Variables
For completeness, we will now go through the above list of global variables, some of which deserve additional comment.
Transcript: a TranscriptStream
Display: a DisplayScreen
Sensor: an InputSensor
The above three globals are widely used, although Sensor is not used directly in Morphic. There the World's hand is the source of input events, and it is not a global because a morphic world may have more than one hands when it is run in multi-user mode.
The transcript is a stream, and it may or may not be open (have a view) on the screen at any given time. There may be a number of instances of TranscriptStream cooresponding to a number of different projects, and, of course, other non-global transcripts may be used elsewhere in Squeak applications.
There should only ever be a single instance of DisplayScreen. There could be one per project, but this would be costly in memory, so the system is written to discard them when switching projects. Each project remembers its display depth so that the corresponding DisplayScreen can be created with that depth. Sometimes a system can come to have several DisplayScreens in it, because Paragraphs have an instance variable that is sometimes set to the global Display. If this does not get nilled out ant the paragraph is held onto, then that displayScreen will be also. If DisplayScreen instanceCount returns a number greater than 1, take a look at the section on Tracking Down Garbage Objects.
Cursor current: a Cursor
Along with Display the current cursor is effectively a global variable, except that it is accessed indirectly through the classPool of class Cursor.
ScheduledControllers: a ControlManager
World: a WorldMorph
These two global variables hold onto the state, not of the Display itself, but of all the objects being displayed on the screen, and sensitive to input events. ScheduledControllers holds onto all the windows and the screenController in MVC. World is the screen-filling morph which, with its submorphs has the analogous role in Morphic. When in MVC, World is nil. When in Morphic, ScheduledControllers SHOULD BE nil, but isn't through 2.3. [Note that, while World tells what morph is in control of the screen in Morphic, one can run Morphic in an MVC window (or several worlds in several windows), and in this case the global World is nil, but there is still a world that can be located in the owser chain of any active morph in any window].
The current project is a global that is accessed indirectly like the current cursor. Projects are used to capture and switch the entire display state. Therefore they store much of the sate alluded to above (World or ScheduledControllers, Transcript, and Display depth -- they should also save Cursor current, but currently the cursor is always restored to normal after a project switch).
SourceFiles: an Array with the sources file and changes file for this image.
Smalltalk: a SystemDictionary
Undeclared: a Dictionary
SystemOrganization: a SystemOrganizer
Smalltalk changes: a ChangeSet
The above five globals capture most of the state of the Devlopment environment. Smalltalk is the dictionary of all true globals. Undeclared is effectively an extension of Smalltalk, as it is a dictionary of all attempted references to globals for which no referent could be found [see How Undeclared Works]. SystemOrganization merely assigns each class to a system category [ClassOrganizers and SystemOrganizers are capable of placing their elements in multiple categories, but this capability has never been used in Smalltalk (for good reason)]. Smalltalk changes holds the active changesSet for the current project. Since this variable is swapped at project switches the structure of recorded changes is as rich as the project structure in a given image.
Processor: a ProcessorScheduler
TranslatorOpcodeEncodings: a Dictionary
ScriptingSystem: a StandardScriptingSystem
ImageImports: a Dictionary
BalloonEngineConstants: a Dictionary
TextConstants: a Dictionary
Other objects that are, effectively global...
Object classPoolAt: #DependentsFields
Most of these containing...
Transcript ImageImports ScheduledControllers Display Sensor SourceFiles SystemOrganization Processor) are simple to create. Similarly, the top-level project is simple to create containing...
there is code in Project to do this).
How Undeclared Works
When a new entry is declared in Smalltalk, Undeclared is searched for a matching entry (remember, a dictionary entry is a real object (an Association)). If found that very entry is installed in Smalltalk, and therefore all the formerly unresolved references suddenly get resolved. This was a significant invention in ST-76.
The Process Scheduler
Proper and improper subclass structures
Obsolete classes - how they get made, why they may persist
How the display works
How events work
The Dependents Dictionary
How things get left in it
How to clean it out
Consistency checks and torture tests
tallySensd and spyOn
Tracking Down Garbage Objects
Making sources internal or external
The startup file.
Various other startups
Fonts and TextStyles