Structure of a Pocket Smalltalk .PRC File

Pocket Smalltalk generates .PRC (Pilot resource database) files which can be transferred to a PalmPilot for execution. Resource databases consist of a list of arbitrary-length chunks of binary data, with each chunk being tagged by a resource type and a resource ID. This document describes the resource types used to encode the different parts of a Pocket Smalltalk program.

Since the compiled .PRC file contains everything needed for execution of the Pocket Smalltalk program, there will be many resource records present in addition to those representing actual compiled Smalltalk source code. These records include the machine language virtual machine, the icon used in the application launcher, some PalmOS GUI resources, and so on. These resources will not be described here.

At the time of this writing, the Smalltalk portion of the compiled .PRC file will consist of one or more of each of the following resource record types (some types are optional):

The resource record type is simply a 4-byte integer which can be conveniently represented as an ASCII string. The resource record abstraction is supported by the PalmOS firmware.

Because of the possibility of memory fragmentation in the PalmPilot, each record is kept to a small size (usually under 8k). If there is more data of a particular type than can fit in a single record, the data is broken up into chunks and each chunk is assigned a consecutive resource ID. This is handled transparently by the virtual machine.

The ClsD Record

The most important segment type is the ClsD type. It contains the compiled form of classes and methods and will usually make up the bulk of a compiled program. It has a somewhat complex layout, but it is logical and efficient. At the highest level, it consists of a header followed by a body. The header has the following structure:

Following this header are the compiled forms of each class. Note: if the ClsD segment needs to be split to avoid fragmentation problems, the split will always occur between the end of one compiled class and the beginning of another.

The compiled form of a class is, basically, a method dictionary. It encodes the selector/method associations of a class. First are two bytes with the number of selectors defined in the class (not counting selectors defined in any superclasses). After this are pairs of 16-bit integers, with the first integer in each pair containing a selector defined in the class, and the second integer in each pair containing the byte offset to the method for that selector (the offset is from the start of the compiled class data, i.e., from the number-of-selectors word above).

The selectors are sorted in ascending order. When looking up a method at runtime, a binary search is performed (in contrast to the hash table mechanism used by other Smalltalks). In general, the binary search is just as fast as a hash table (and faster for classes with large numbers of methods), and it saves space because there are no usused slots.

After the selector/offset table come the instructions of the methods, one after the other. The methods are completely linear; in other words, no "literal table" is needed. Therefore compiled methods need no extra structure and need not be scanned by the garbage collector at runtime.

Other Segments

The other segments will be described here in a later version.
Andrew Brault (ajb@tiac.net)