Planet Smalltalk

January 29, 2015

Torsten Bergmann - PunQLite - simple NoSQL for Pharo

I updated the PunQLite project - now including a simple database brower. Read more


Torsten Bergmann - PharoDays2015 start

The Pharo Days 2015 conference starts today. You can follow some of the news with the Twitter hashtag: #pharodays2015

January 28, 2015

Torsten Bergmann - Object oriented implementation of numerical methods now OpenSource

Didier Besset offered his great book “Object-Oriented Implementation of Numerical Methods" to the community.

Read more here or directly grab the PDF.

Pharo Weekly - Object-Oriented Implementation of Numerical Methods now open-source

Didier Besset offered his great book “Object-Oriented Implementation of Numerical Methods:
An Introduction with Smalltalk and Java” to the community.

We would like to thank Didier Besset for his great book and for his gift of the source and implementation to the community.

You can find

Both book versions are maintained by Stéphane Ducasse and Serge Stinckwich.

27 Janvier 2015

Torsten Bergmann - GLORP Resources

Want to get used to GLORP, the ORM for Smalltalk to access a RDBMS from your favorite Smalltalk dialect. Then check out these resources:

January 27, 2015

Pharo News - [ANN] Pharo Consortium New Academic Partner: FAST

<p>The Pharo Consortium is very happy to announce that the FAST: Fundación Argentina de Smalltalk has joined the Consortium as an Academic Partner.</p> <p>About</p> <ul><li> FAST: Fundación Argentina de Smalltalk: <a href=""></a></li><li> Pharo Consortium: <a href=""></a></li></ul> <p>The goal of the Pharo Consortium is to allow companies and institutions to support the ongoing development and future of Pharo. Individuals can support Pharo via the Pharo Association: <a href=""></a></p>

Pharo News - [ANN] Pharo Consortium New Academic Partner: FAST

<p>The Pharo Consortium is very happy to announce that the FAST: Fundación Argentina de Smalltalk has joined the Consortium as an Academic Partner.</p> <p>About</p> <ul><li> FAST: Fundación Argentina de Smalltalk: <a href=""></a></li><li> Pharo Consortium: <a href=""></a></li></ul> <p>The goal of the Pharo Consortium is to allow companies and institutions to support the ongoing development and future of Pharo. Individuals can support Pharo via the Pharo Association: <a href=""></a></p>

Yoshiki Ohshima - [仕事] プロファイラのバグ

なんだってー!! 前のプロジェクトでSqueakを使っていた頃は結構QSystemProfiler(改名されてAndreasSystemProfierとなった)の結果を当てにしていたのですが、まさか抜けがあったとは。バグ逃げされたー。

January 26, 2015

Torsten Bergmann - MapReduce, Hadoop, and Cincom Smalltalk

Torsten Bergmann - Squeak for DiamondTouch

Sebastian pointed me to  today. Have not seen this page before.

The page includes a Squeak app for DiamondTouch (DiamondTouch table is a multi-touch, interactive PC interface). From the people page it looks like Jochen “Jeff” Rick helped shaping it, I know him from his Swiki implementation and Squeak and Pharo contributions like QRCode.

He wrote several apps in Smalltalk as you can see on his page. Nice!

Torsten Bergmann - Microkanren for Pharo

An implementation of µKanren (an embedded Domain Specific Language for logic programming) for Pharo. The project is here (GitHub) and here (SmalltalkHub).

Torsten Bergmann - Pharo presentation in Mons

Torsten Bergmann - PharoCloud with PillarHub knowledge base

PharoCloud now uses own PillarHub to provide a knowledge base:

Also Pharo Launcher is part of their Pharocloud Image Store. Additionally the underlying cloud system provides support for Cairo graphics which makes it possible to run Pharo4 on it and access it via VNC.

Torsten Bergmann - Pharo Days 2015

January 25, 2015

Smalltalk Jobs - Smalltalk Jobs – 1/24/15

  • Bengaluru/Bangalore, IndiaSmallTalk Developer at Cargill
    • Required Skills:
      • Bachelor’s degree in Computer Science/ MIS or a minimum of 5 years of software development experience.
      • SmallTalk VSE
      • SmallTalk Visual Works 7.9
      • SQL
      • Strong problem solving skills.
      • Ability to follow complex documentation.
      • Good verbal and written communication skills.
      • Ability to work in a team environment.
      • Ability to handle multiple priorities and meet deadlines.
      • Familiar with software design concepts, standards, practices, and procedures.
  • Windsor, CT and Lafayette, LAApplication Developer through Ardice Consulting
    • Required Skills:
      • Visual SmallTalk Enterprise(VSE 3.1)
      • Window builder pro
      • Overall 7 + years IT experience with minimum of 3+ years into design and lead developer/tech lead role.
    • Wanted Skills:
      • Health insurance domain knowledge
      • .Net.
      • ASP .Net
      • C#
      • VB.Net
      • SSRS
      • SSIS
      • SQL Server
      • Crystal Reports
      • RDLC Team player
      • Strong leadership qualities
      • Onsite-Offshore coordination Effective communication
      • Analysis and Design skills
    • Additional listings: CGI, CGI, CGI, CGI, Ana Data Consulting
  • White House Station, NJSmalltalk Consultant through Windsor Partners
    • Required Skills:
      • 8+ years of experience on IBM VisualAge Smalltalk
      • Strong OOPS Concepts
      • Strong design and development skills on Smalltalk
      • Knowledge of Smalltalk version 8.5
      • Knowledge of Smalltalk Server
      • Knowledge of writing Web Services in Smalltalk
      • Ability to create high level (Conceptual) and Low Level design
    • Wanted Skills:
      • Insurance domain knowledge will be an advantage particularly Property & Casualty.
    • Additional listings: Windsor Partners, Okaya, Lorven Technologies
  • Charlotte, NCSmalltalk Developer through Kforce
    • Required Skills:
      • Bachelor’s degree in Computer Science, Information Technology, or equivalent is required
      • Must have 10 + years’ experience with Smalltalk programming and debugging/troubleshooting with Cincom ObjectStudio or equivalent
      • 5 + years in client server application development
      • SQL Server
      • Experience with agile and waterfall software development methodologies
      • Ability to translate business requirements into technical requirements
    • Wanted Skills:
      • Knowledge of Quality Center
      • Knowledge of Microsoft SharePoint
    • Additional listings: Kforce, Kforce
  • Miami, FLApplications Architect through Kforce
    • Required Skills:
      • Java Skills
      • Smalltalk
      • VB.Net
      • Must have strong communication and people skills
    • Wanted Skills:
      • Java AND .Net is a plus
Good luck with your job hunting,
James T. Savidge

View James T. Savidge's profile on LinkedIn

This blog’s RSS Feed

Filed under: Employment Tagged: jobs, Smalltalk, Smalltalk jobs

January 24, 2015

Pharo Weekly - Another batch of improvements

14784 toggle show hierarchy gives: list receiver of “package” is nil

14779 fix #definitionString for subclasses of ClassVariable and IntanceVariableSlot

14780 Bug in compiled method printing since signflag is printed.

14775 Cleanup “Jobs” package further

14770 Clean up the AST-Interpreter package further

14766 Fix two release methods in Versionner

14768 MCClassDefinition: merge #createClass into #load

14755 Slot: do not call #index: on virtual slots

14753 add support for setting class comments to class builder


14636: spotter: remap cmd+enter to shift+enter
14641: spot on global vars
14741: GTInspector: add simple slot support
14252: Make collections browsable again in the tools
14722: Disable FreeType gives MNU and RMOD in GTools
14711: The Playground print popper should allow for inserting the text in the editor
14587: deleting the whole text in the inspector pane throws SubscriptOutOfBounds
14515: Damaged configurations in the image
14742 Fix: Allow defining simple ClassVariales using symbols

14712 The print-popper should have a different color than the selection in the default Pharo theme

14515 Damaged configurations in the image

14733 do not check for coding convention on addClassVariable:

14731 Fixing DNU binding in GT and Nautilus

14590 SHParserST80Test>>#testNumbers

14725 When using class side slot, show class definition for slots

14720 Add support for Class Instance Slots

14716 Remove all #notify: from inline checking

14718 Move class instance variable def from #load to #createClass in MCClassDefinition

14699 Slot: #definingClass and #usingMethods should work on non-used slots

14698 Allow Slots to be saved with Monticello

14697 simplify extended search menu: case insensitive description not needed

12501 Duplicate shortcut case sensitive/insenstive method literal strings with it

14691 Improve pretty printing of Slot classdefinition

14693 Spotter version 1.0.6

14692 GTools version 2.0.8

14684 Spotter version 1.0.5

14683 GTools version 2.0.7

14681 Commiting to directory with subdirectory repo

14680 Improve printing of class definition of classes with Slots or ClassVars

14638 Avoid indirectly invoking the Refactoring Engine parser (thru CompiledMethod>>ast) when installing a method from an used trait

14679 Fix layout glitch in FileDialogWindows text preview

14678 fix DNU #index when redefining a class with slots that have no index

14675 correctly set superclass when creating classes with slots

14672 ScriptLoader should not reset repositories

14673 Avoidable DNU at each compilation

14668 HandMorph event statistics should be off by default with preference

14652 Float class fromIEEE32Bit: gradual underflow handling is buggy

14658 cleaning/commenting SUnit classes

14643 find records for classcomment changes in SourceFileArray

10529 ToolRegistry need to support multiple registrations per tool

January 23, 2015

Arden Thomas - MapReduce, Hadoop, and Cincom Smalltalk

MapReduce is a popular and effective technique that’s used to apply concurrency to problems that often involve large amounts of data, in order to improve performance.

Hadoop is a popular implementation of the MapReduce model or technique.

MapReduce is named after the functional programming functions map and reduce. The map function applies a function to each element in a list, and reduce aggregates or combines the results. MapReduce can distribute the Map work to many machines, and then Reduce summarizes the work into a final answer.

MapReduce and Smalltalk

So how would this work in Smalltalk? To start, let’s determine what the Smalltalk equivalents to map and reduce are.

The collect: method can be used as a Smalltalk equivalent of map, since it can collect the result of a block applied to every element in a collection.
The fold: method (or inject:into: ) can be used as an equivalent of reduce, since it can reduce the results to a single object (simple  examples: finding the maximum, minimum, or sum value).

Pragmatically though, you might also think of map as mapping out the work (to be performed concurrently) to multiple cores or machines, and reduce as combining or summarizing the results from the map work. If you are following the pattern it doesn’t matter if  you use collect: or fold: specifically.

The purpose of Cincom’s MatriX framework is to simplify concurrency. The MatriX framework allows you to easily make many linear solutions concurrent.

The example below shows how to create a solution to a problem, and then use MatriX to create a mapReduce-style solution using the same code with minimal alterations.

A Simple Example

Let’s say that we had a long list of documents (files) and we wanted to get a count of how many times each word occurs in the set of documents. In Smalltalk, we would want to collect the word counts for each file and then combine or fold the results into an aggregated summary.   So how might we do this in Smalltalk?

Let’s start with some basics.

  1. A method to return a list of filenames to use for counting word occurrences
  2. A method that parses the file into tokens (words)
  3. A method that, given a file string, returns a count of the words found in the file
  4. A method that summarizes (reduces) the word counts into one set
  5. A method that provides a local solution using the above methods

We can test and debug by first running it locally, and then move forward distributing the work.

Below are the methods for the above basics, respectively:

Note: Be sure to change the dir in the myFiles method to a location on your machine.

        "self myFiles"
        "Returns filename strings"
        | dir fileStrings |
        dir := 'C:\Arden\Documents\Cincom\'.
        fileStrings := dir asFilename filesMatching: '*.txt'.
        ^fileStrings as Array


parseFile: fileString
        | fileStream contents words |
        fileStream := fileString asFilename readStream.
        contents := [fileStream upToEnd] ensure:[fileStream close].
        words := contents tokensBasedOn: Character space.
        words copy do:[:word | (word includes: Character cr) ifTrue: [
               words remove: word.
               words addAll: (word tokensBasedOn: Character cr)]].

wordCountFor: fileString
        | words |
        words := self parseFile: fileString.
        words := words collect:[:word | word select:[:char | 
		char isAlphabetic] ].
        words := words reject: #isEmpty.
        ^words asBag.


reduce: wordCounts
        "Combine the wordCounts and create a Dictionary summary"
        | aggregatedWords finalCounts |
        aggregatedWords := wordCounts fold:[:counts :newCounts | 
		newCounts valuesAndCountsDo:[:word :n | 
		counts add: word withOccurrences: n]. counts ].
        finalCounts := Dictionary new.
        aggregatedWords valuesAndCountsDo:[:word :count | 
		finalCounts at: word put: count].


        "self runExampleLocal"
        | files wordCounts summary results |
        files :=self myFiles.
        wordCounts := files collect:[:fileStr | self wordCountFor: fileStr ].
        summary := self reduce: wordCounts.
        results := summary associations sort: #value descending.
        (results first: 100) do:[:ea |Transcript cr; show: 
		ea key; tab; show: ea value printString ].

So now that we have this running, we want to distribute the workload to allow the files to be processed and words to be counted, concurrently. The word counts will come back to a central place (our main image) where they will be summarized.

Making this concurrent is a lot of work, right?

Not in Smalltalk with Cincom’s MatriX concurrency framework.

  • Load MatriX
  • Add one line of code to create the virtual machines that do the work concurrently
  • Tweak the line of code that gets the word counts to distribute the work

That’s it! Here is the complete example of our solution running distributed:

        "self runExample"
        | files vms wordCounts summary results |
        files :=self myFiles.
        vms := MatriX.VirtualMachines new:3.
        wordCounts := [vms do:[:fileString | 
		MapReduceExample wordCountFor: fileString] with: files] 
		ensure:[vms release].
        summary := self reduce: wordCounts.
        results := summary associations sort: #value descending.
        (results first: 100) do:[:ea |Transcript cr; show: ea key; 
		tab; show: ea value printString ].

Note: I ran into an issue with marshaling Bags in MatriX, and I have a patch available. (Thank you Michael for finding and fixing!)

Torsten Bergmann - Smalltalk Research forum

Richard Eng (initiator of the Smalltalk Renaissance Program - SRP) will now use the Smalltalk-research forum!forum/smalltalk-research

to discuss all future SRP-related discussions. So if you want to participate in SRP go there.

Torsten Bergmann - Dark Theme for Amber Helios IDE

The Amber Smalltalk Helios IDE also supports (similar to Pharo) a dark theme. Nice!

Joachim Tuchel - Instantiations survey: Which Smalltalk are you using?

Instantiations put up a mini-survey to better understand the current Smalltalk market. They only ask one single question: What flavor (or flavors) of Smalltalk do you actively use? So if you are using Smalltalk, or even if you are just interested in using Smalltalk, please take 20 seconds to answer this simple question. There is […]

Torsten Bergmann - SmalltalkFlavor

There is an online survey from Instantiations: what Smalltalk flavor do you use?

January 22, 2015

Ricardo Moran - Conway’s Game of Life

Hi everybody,

Playing with Laura’s “Programming Minecraft” project I made a very simple implementation of Conway’s Game of Life. Just for fun :)
Here you have a video:

Hola a todos, estaba jugando con el proyecto de Laura “Programando Minecraft” y armé una muy simple implementación del Juego de la Vida de Conway. Sólo para divertirme un rato :)
Acá les dejo un videito:

Cincom Smalltalk - Smalltalk Digest: January Edition

The January edition of The Cincom Smalltalk Digest is available now.

January 21, 2015

Pharo News - [ANN] Pharo Consortium New Academic Partner: DCyT - Universdad Nacional de Quilmes

<p>The Pharo Consortium is very happy to announce that the DCyT - Universdad Nacional de Quilmes has joined the Consortium as an Academic Partner.</p> <p>About</p> <ul><li> DCyT - Universdad Nacional de Quilmes: <a href=""></a></li><li> Pharo Consortium: <a href=""></a></li></ul> <p>The goal of the Pharo Consortium is to allow companies and institutions to support the ongoing development and future of Pharo. Individuals can support Pharo via the Pharo Association: <a href=""></a></p>

Pharo News - [ANN] Pharo Consortium New Academic Partner: DCyT - Universdad Nacional de Quilmes

<p>The Pharo Consortium is very happy to announce that the DCyT - Universdad Nacional de Quilmes has joined the Consortium as an Academic Partner.</p> <p>About</p> <ul><li> DCyT - Universdad Nacional de Quilmes: <a href=""></a></li><li> Pharo Consortium: <a href=""></a></li></ul> <p>The goal of the Pharo Consortium is to allow companies and institutions to support the ongoing development and future of Pharo. Individuals can support Pharo via the Pharo Association: <a href=""></a></p>

Torsten Bergmann - Grafoscopio

Grafoscopio is a mockup of a outliner interface made using Moose playgrounds. Is a learning exercise from a Smalltalk newbie but it aims to evolve to become a outliner interface for playgrounds that can be used for developing visual data narratives for open/garage/citizen science research.

A detailed description is here, video here and code here.

Torsten Bergmann - NBSQLite3 for Pharo, accessing RDBMS via Glorp and more Pharo persistence options

There is a new way/project to work with the SQLite3 embeddable database. While in the past there was already a SQLite wrapper project for Pharo based on FFI this new one is based on NativeBoost and also has some support for Glorp.

The project is called "NBSQLite3 for Pharo". Read more in my original announcement to get all the details.

Original binding for NativeBoost was written by Pierce Ng. After that I refactored the bits and pieces a little bit, repackages for better loading and added a ConfigurationOfNBSQLite3 to it (one can load the core independent from Glorp support, etc).
Additionally as the old version was hosted on SqueakSource3 it was also moved over to SmalltalkHub:!/~PharoExtras/NBSQLite3

The STHub project page includes some docu. Meanwhile I also fixed encoding issues between SQLite3 (UTF-8 storage format) and Pharo (Multibyte characters). The nice thing is that with SQLite as small embeddable database you just need a shared library (sqlite3.dll for Windows for example) and you can have a full relational database(s) in single files.

If you are already using Pharo 4 then you can directly install it right from the config browser. Guillermo Polito additionally now created a CI job for it on the DBXTalk CI Server.

You can use the NBSQLite3 package to directly access the relational database and send SQL commands to it. But this is very cumbersome. A better way is to use an object relational mapping framework and Smalltalk has the Glorp ORM framework for that.

If you want to use NBSQLite3 together with Glorp on Pharo4 then you should have a look at this short tutorial I wrote. Also have a look at Svens excellent article on how to use Glorp in Pharo with PostgreSQL and the various descriptions on the Glorp website.

As of today Debris (a company who also joined the Pharo consortium) made a project and code available to use different backends while still working with the Glorp interface. This project is called DebrisDB and is also hosted on SmalltalkHub. If you use it right, you can back your application by Fuel files, SIXX files, any serializer, Gemstone, or Glorp/SQL, without modifying your application code.

For sure database support for Pharo will move on in 2015 and open much more possibilities.

Side note: if you dislike relational databases you can even have a small embeddable NoSQL database with Pharo that also only requires a simple shared library to package with your app. It is called "UnQLite" and I already posted about the PUnQlite binding for Pharo. You can even use Mongo or others with Pharo. If this is an option for you do not forget to have a look at Voyage which makes persistency very easy. There is also SandstoneDB, Magma and SimplePersistence.

And not to forget that there is Gemstone allowing you to work with persistent object as if they were in the Smalltalk image.

Clément Béra - Context and BlockClosure implementation

Today I’m going to discuss about the internal representation and the implementation of Contexts and BlockClosures running on top of the Cog VM (that includes Pharo, Squeak, NewSpeak contexts and closures).


First things first, what is a Context and what is a BlockClosure ?

A Context represents the state of a method activation. A Context is created when a method is activated, and is terminated when the method’s execution is finished (the method has returned). This means that several contexts can exist for a single method if the method has been activated several times.

In many languages, a method activation is defined as a stack frame. In Smalltalk, a context is different from a stack frame because it is manipulated as any object and on the contrary to stack frames, a Smalltalk context *can* edit its sender/caller (i.e. the context that activated it).

A BlockClosure is a reference to a function together with a referencing environment. A BlockClosure is interesting because in addition to a method, it encapsulates the environment that created it. By referencing this environment, it has two features that regular methods do not have:

  • Access to non local variables
  • Non local returns

Method’s context

Methods are represented by CompiledMethod objects. Without going into details, a compiledMethod holds information about what code the virtual machine has to run in the form of bytecode instructions.

When a method is activated, a Context is used by the virtual machine to access the runtime state of the method. The virtual machine needs several information to be able to execute an instruction in the compiled method:

  • sender: the sender references another Context, the one that activated this context.
  • pc: pc stands for program counter. It can also be called sometimes ip for instruction pointer. The pc holds a number so the VM can know which bytecode instruction it is currently executing and which instruction is the next instruction to execute.
  • method: we said that a context is a method activation. The method references the method that is activated by this context.
  • receiver: when executing instructions such as ‘self’ or instance variable access, the VM needs a pointer towards the receiver object
  • arguments and temporary variables values: All the values of the temporary variables and arguments are stored in the form of a stack. A Context has an instance variable, stackp, which represents the current depth of the stack, and a variable-sized zone to store all the values.


self feedSnowLeopard.
self feedLion.
self feedMonkeys.
self feedTiger.
self feedPanther.

| bananas |
bananas := self fetchBananas.
self putFood: bananas in: zoo monkeyCage.

DoIt: ZooKeeper new feedAllAnimals

If you debug step by step the DoIt, you can see in the debugger the method feedMonkeys and its the call stack in the form of contexts.


Each line in the debugger corresponds to a method activation, aka a Context. Each context has a reference in its sender field to the next context in the list.

Let’s *basic inspect* the top context.


As we can see in the inspector and in the figure below, the sender field references the context for ZooKeeper>>#feedAllAnimals that activated this context for ZooKeeper>>#feedMonkeys. The pc field represents the next bytecode instruction that will be executed, ‘send monkeyCage’. The stackp field represents the current depth of the stack, which is 4. The method field references the compiled method for which this context was created. The closureOrNil field is always nil for method activations (we’ll discuss closure activations later). The receiver field holds a pointer to the receiver.


Let’s detail the stack zone. This zone has a variable size. For performance, the Cog VM preallocate room for the Context stack based on a flag in the Compiled method (it preallocates either 16 or 56 fields depending on the flag, see the largeFrame and SmallFrame class variable values of CompiledMethod). Thanks to stackp, the Context knows which fields it is allowed to access in its stack zone (other values on stack may not be safe).

In our case, the context can access 4 values on stack. For method activations, the stack is composed as follow:

  • arguments values
  • temporary variables values
  • additional stack slots

The method studied, ZooKeeper>>#feedMonkeys has no arguments. So this area is empty in our case. It has however 1 temporary variable, bananas. This is why the first stack slots holds bananas, this is the value of the temporary variable (when executing bananas := self fetchBananas, the temporary was assigned to a collection of bananas. Before these instructions, it was nil).

The additional stack slots are there for runtime support. For example, when a message send is activated, the VM push on stack the receiver and the arguments of the message. In our case, we are about to send a nested message send. The elements on stack at position 2 and 3 are the receiver and first argument of the message send #putFood:in:, whereas the element at 4 on stack is the receiver of the #monkeyCage message.

Ok, we explained the basics, now let’s move to the advanced cases: BlockClosure creation and activation.

BlockClosure creation

A BlockClosure is created to encapsulate its enclosing environment. It encapsulates:

  • accesses to non local variables (non local temporary variables, non local arguments, enclosing environment receiver)
  • direct access to the enclosing environment for non local return (If you don’t know what’s a non local return, please read the Block chapter in Deep into Pharo)
  • access to the code to run to execute the closure (in the form of bytecode instructions

Example: (N.B.: This example is convenient as a showcase, it’s not necessarily recommended code)

playWithMonkeysWith: toys
1  | issue |
2  issue := false.
3  zoo monkeyCage getMonkeys do: [ :monkey |
4    monkey isMad
5      ifFalse: [
6        self playWith: monkey with: toys.
7        self isHarmed ifTrue: [ issue := true ] ]
8      ifTrue: [ issue := true ].
9    issue ifTrue: [ ^ self leaveMonkeyCage ] ]

Let’s look at the block created as an argument of the #do: message line 3,
[ :monkey | "..." ].

This block has access to the variable issue, created in the method’s context, and to the argument of the method toys. These variables are not defined in the block, so they’re non local. This kind of variables typically do not exist in regular methods.

This block has also a non local return line 9: if there was an issue, the ZooKeeper leave the monkey cage without playing with the other monkeys.

Let’s debug the BlockClosure and inspect it (step by step, then inspect the closure when it’s on stack top, I’ll show a scheme because it’s simpler to explain).


The BlockClosure is created with a certain number of copied variables, in our case, 2, issue and toys. This is why our BlockClosure has two extra variable fields.

The outerContext of the BlockClosure is the context that created it, it is the method activation record of playWithMonkeysWith:.

The method encapsulated by the blockClosure is represented as bytecodes inlined in its enclosing method. Therefore, a blockClosure can access its bytecode by looking for its outerContext method and its bytecode starts at the program counter stored in its instance variable startpc. In the figure, we indented the bytecodes of the blockClosure in the method. When the method is executed, after the block creation, it jumps over the block bytecodes. The block bytecodes are used only in the block closure activation.

The numArgs field of the BlockClosure holds 1, because the block has one argument monkey.

Now we have two copied variables, holding toys and #(false). toys is the argument of the enclosing method. As the argument is not assigned in the block closure nor after the block creation, the value of toys will remain the same after the block creation. Therefore, we insert in the block a copy of the variable toys, allowing the block to access it.

On the other hand, the variable issue is assigned in the blockClosure. As the variable is shared between the enclosing method and the closure, when issue is edited, the variable needs to be edited in both place. To do that, the compiler automatically generates the creation of an array (See instruction 45, push (Array new: 1)). This array, allocated on heap, holds the variables that are shared between the closure and the method and that couldn’t be passed as a copy because of the position of some assignments. We saw that the second copied value of the block was #(false), this is in fact the value of the variable issue nested in an array.

Variables that are accessed through an indirection array are not accessed with the same bytecodes than regular variables. At instruction 55, we can see a pushTemp: 0, which means it accesses the first value on the context stack, the argument of the method toys. At instruction 49, popIntoTemp:0 inVectorAt: 1, we can see an access to a temporary in an indirection array. This bytecode means, access the first field of the array located at position 2 on stack.

Note: Arrays created automatically for variable shared between closures and methods are also called tempVectors or vectors.

1) Typically, a blockClosure has access to only 1 temp vector that can have up to 255 variables and multiple copied temporary variables. However, in specific cases (multiples closures including nested closures and inlined closures), a blockClosure may have access to several temp vectors.

2) While debugging, the user can see in a blockClosure its temporaries including the copied temporaries. He can also edit their values. In this case, the debugger figures out that several fields need to be edited, the field in the blockClosure activation, the field in the blockClosure itself, the field in the enclosing activation, and fix them all.

Non local returns

Yesterday I looked up the definition of a closure and I found this one:

In programming languages, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment — a table storing a reference to each of the non-local variables of that function. A closure — unlike a plain function pointer — enables a function to access those non-local variables even when invoked outside its immediate lexical scope.

The definition started well, until they described the referencing environment as “a table storing a reference to each of the non-local variables of that function”. Then the definition is not correct anymore because in some implementation the referencing environment is more than just a table. That’s the case in Smalltalk.

A blockClosure has a direct pointer to its outerContext, the context that created the blockClosure. With this variable, the blockClosure can access any temporary variables (even the ones it does not need), as well as perform non local return.

1) Why would the blockClosure want to access temporary variables it does not need ? One simple answer: to improve the debugger. In the debugger, the user can see the values of any temporary variables, disregarding if it’s a copied variable, indirect variable or unused variable (you don’t even have to understand such concept to debug your smalltalk code).

2) If the blockClosure can access the non local variables from the outerContext, why does it need to keep references to them in its variable fields ? For performance mainly. Using directly a context is difficult as the virtual machine maps the linked list of contexts to a C-like stack internally. Therefore one wants to limit the access to the contexts for performance.

3) What’s a non local return and do we care ?

Ok here’s the main point. A blockClosure can return either to its sender (see our example with false as argument) or to its homeContext sender (see our example with true as argument). This non local returns requires the virtual machine to walk up the stack until it finds the stack frame to return to. This can be done only using the outerContext field.

This outerContext field is therefore kept to be able to perform non local returns and to be able to debug a blockClosure seeing all the temporaries disregarding of their status with the blockClosure.

We care about non local returns because in smalltalk, conceptually, all control structures (conditions, loops) are messages sends with blockClosures as arguments. If we wouldn’t have non local returns, we wouldn’t be able to write a return in a branch or in a loop.

self isPlague ifTrue: [^ self].
“some code…”

This method conceptually requires a non local return.


1) Non local return to dead home context

If a block holds a non local return, the execution flow will returns to its home Context sender. However, it can happen that the block’s home Context is already dead.


self getBlock value

^ [ ^ 42 ]

In this case, while executing the blockClosure (value message), the blockClosure outerContext, the activation of getBlock, is already dead. Therefore an exception is raised (BlockCannotReturn).

2) Sideway return

Sideway returns is one of the trickiest aspect of non local returns. It is not specified in the Smalltalk specifications, so it is the choice of the VM implementors to allow them or not. In the Cog VM, they are strictly forbidden.

A sideway return happens when a block performs a non local return, with it home Context alive but not on stack.


[ ^ 42 ] forkAt: Processor activePriority + 1.
Processor yield.

Here, when the non local return of the block is performed, its outerContext (the activation of exampleSidewayReturn) is alive, but on another Process stack. This is a sideway return and also raises a BlockCannotReturn on the Cog VM.

Activating a BlockClosure

When a BlockClosure is activated, conceptually, a context is created as for method activations. There are 2 main differences in blockClosures activations:

  • a reference to the blockClosure is held by the context in the field named closureOrNil This field is nil for method activations, and references the closure in case of closure activation. This field is used, for example, to find out the home context of the blockClosure activation using the block closure outerContext.
  • In the stack zone, we can find first the arguments of the block, then the copied variables of the block, then the temporary variables for the block before the additional slots (see figure below)


Performance details

When a blockClosure is created, up to three objects are created:

  • the blockClosure to holds the outerContext, the references to non local variables, the number of arguments of the closure and the start pc to know what bytecode to execute while running the closure
  • the outerContext (i.e. the mapping between the outer stack frame and a context object): this is not needed if the outerContext has already been created, for example by another closure creation
  • the tempVector to store indirect temporaries

To improve performance, one has to reduce the number of objects created. One solution is to try not to have tempVectors, by rewriting the blockClosure differently to avoid the tempVector creation. Another solution is the adaptive optimization approach we are currently working on, which aims to inline the blockClosure in its homeContext, in order not to create any of these objects.

Some other smalltalks, such as VisualWork smalltalk, decided to keep the outerContext field of blockClosures only if a non local return is present in the closure. This makes it harder to debug, because the user cannot see from the blockClosure which activation created the closure nor unneeded temporary variables from the enclosing environment. This optimization would be tricky in Cog because Cog’s blockClosure relies on the outerContext also to find out where is the method holding the bytecode to execute for a blockClosure (the blockClosure bytecode is inlined in the enclosing method bytecode).

Pharo Weekly - DebrisDB Project published allowing Glorp style without SQL servers

The Debris Publishing Team released its Toolkit!

DebrisDB Project published under the MIT License.

This toolkit allows programmers to use the Glorp interface without a Glorp-system definition, and without needing any SQL servers up an running. If you use it right, you can back your application by Fuel files, SIXX files, any serializer, Gemstone, or Glorp/SQL, without modifying your application code. Therefore, it is perfect for prototyping concepts very quickly.

user: ”
password: ”

See the project description for more information.

Good Luck from the Debris Team!