Coming from another Smalltalk

Smalltalk MT (STMT) has many similarities to other Smalltalks but because this is compiled Smalltalk there are a number of necessary differences.

  1. In the Source subdirectory of the STMT installation you will find SMALLTALK EXTENSIONS.SP, SMALLTALK SYSTEM EXTENSIONS.SP and SMALLTALK.SP. These projects include some abstractions that may be helpful when moving to STMT.
  2. An object pointer in STMT is actually the address of the object. Sending an object basicAddress returns this pointer and this will be constant for the life of the object.
    The object header is 8 bytes back from this pointer.
    To demonstrate this, in one workspace enter str := 'abcde'. Now evaluate str basicAddress. This will return a 32 bit number (both the objects address and its hash value). Copy this number into another workspace and send it _asObject and inspect the result. You will get the same string back. This is similar to a GemStone object identifier.
  3. Objects can live in one of four places depending on the allocation method.
    Object Memory which uses Virtual Memory when allocated with new.
    The stack which uses a Frame Allocation when allocated with localNew.
    Heap Memory which uses the Private Heap when allocated with heapAlloc.
    MMF memory when used in a Memory Mapped file (see classes MemoryStream and MappedObjectStream).
  4. Since Windows manages the memory for all allocation types, STMT is not concerned about memory fragmentation or having to move objects around in memory.
  5. DLL's can be statically loaded into the image. Image properties allow you to add a DLL. On an image save the DLL header is bound directly into the new image. When the image is brought up next, all of the DLL entries are available inline.
  6. APIs can be called directly. For example try to evaluate
    WINAPI strlen: 'My string' basicAddress
    strlen is an API in the C runtime library which is included as part of the STMT environment. STMT makes extensive use of the C runtime library instead of recreating this functionality. The C runtime library is fully documented in both the MSDN library (http://msdn.microsoft.com) and the MC Visual C/C++ documentation.
    Note that API calls are faster than message sends. On encountering a WINAPI, the compiler generates code to push the arguments on the stack and jump to the API address directly.
  7. Some messages are inlined which means that the compiler knows how to generate code for them directly. An example of this is anObject _longAtOffset: 4.
    There is no compiled method object so grep is used to find senders, implementors and instance variable references. This means that strings in comments will show up. There is also a query in the Class Hierarchy Browser (CHB) which will search for strings across methods (current class or all classes). In the CHB, methods can also be found by typing their name.
  8. When you send fork or forkAt: to a context block, the context block runs in its own windows thread. This means that you must be concerned about synchronization if multiple threads touch the same objects. See the Philosophers sample for an example of multi-threading.
  9. Categories are more than just a way of classifying methods. They advise the compiler of the type of a method. Putting a method into the category .INTERNALDEV for example means that the method is available in the development environment but will not included in a runtime project. If you don't want to see categories, they can be turned off in the View Menu of the Class Hierarchy Browser. 
  10. Projects are the way to manage source code. Multiple projects can be loaded into the development environment and projects can specify other projects as prerequisites. A project is required to create a runtime application.
  11. You can expand up the method pane to full-size using Ctrl-Z.
  12. Ctrl-Break (i.e. user break) is done by using the ThreadViewer. Start the Thread Viewer from the Tools menu in the Transcript. This load a tray program (look in the task bar tray). Opening this will show all the currently running threads. Thread #0 is the main process thread. Selecting this thread and pressing Break will cause an exception to be sent to the main thread. Then you can debug where this exception happened.