links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
Last updated at 7:40 pm UTC on 4 April 2017

Eliot Miranda
Tue, Apr 4, 2017 at 8:16 PM
Reply-To: Pharo Development List
To: Pharo Development List

Hi Pavel,

On Tue, Apr 4, 2017 at 1:15 AM, Pavel Krivanek wrote:


 > Then I had here a really huge image with 1.2 GB with all known memory leaks solved. It was leaking because of Undeclared, after cleaning of them 
 Undeclared removeUnreferencedKeys) 
 > it shrinked to 59 MB. 

Cleaning Undeclared arbitrarily is a very bad idea. Undeclared is where we can find and eliminate Undeclared variables. Just eliminating them from Undeclared does not solve the problem. The variables are still referenced in coded. But when one removes them from Undeclared they become harder to find.

Instead the right solution is
a) to have tests in the standard test suite that check that Undeclared is empty. If Undeclared is not empty the test should fail.
b) in any packaging or release process that produces a clean image there should be a check for Undeclared being empty, and the build should fail if it is not empty.
c) Smalltalk programmers should understand how undeclared variables work in Smalltalk:

Variables are declared either in some global pool such as Smalltalk, TextConstants or a class pool (the dictionary holding class variables), or as instance variables of a class, or as arguments and temporary variables of a method. These are the only variables in the language. When the compiler sees a variable name it searches for it, first amongst arguments and temporaries, second amongst instance variables, third amongst class variables, fourth amongst the class's imported pools, fifth in globals (Smalltalk) and finally in Undeclared. If the variable is not found in any of these places then a binding is created in Undeclared and that is used to implement the variable. So undeclared variables are compiled as globals in Undeclared.

Whenever a variable is declared in a global pool (Smalltalk, a shared pool or a class pool) the compiler checks for a binding in Undeclared and uses that if it exists. Adding a class declares the class's binding in Smalltalk. So uses of variables before they are declared get fixed up on declaration without having to recompile the entire system. This is how the system manages circularities amongst classes. A reference to a class that has yet to be installed will be compiled as a reference to a binding in Undeclared. When the class is installed it is set as the value of the Undeclared binding, and the binding is moved from Undeclared to Smalltalk.

When an instance variable is defined in a class that changes the shape of the class's instances and so the class's methods are recompiled and that will bind any undeclared references to the instance variable correctly.

So an entry in Undeclared is
a) an indication that somewhere there is a missing declaration
b) a place where one can look for references to the undeclared binding (references in the dictionary inspector, and I hope the Glamour inspector, that opens when one inspects Undeclared)
c) a simple mechanism for allowing circular references amongst classes

So under no circumstances remove bindings from Undeclared unless there are no references from code to those bindings. There is a method that does this:
Undeclared removeUnusedBindings