Sunday, August 28, 2011

Class format

I want to add more instance variables to Class. How difficult is this? Pretty. I suspect that for vanilla Squeak or Pharo, you'd need to carefully remake every single Metaclass instance and Class instance. For me, my Packages architecture means I only need to recompile my own private Metaclasses and all its instances which can be done safely.

Before I started though, I wanted to see what happened if I did something wrong: what happens if I add the extra variables to Class, but instances and subclasses of Class (i.e. every single class and class class) were not updated?

Classes in the Squeak VM have three variables very important variables which are referenced directly by the VM: superclass, format and methodDictionary. The format describes the nature of instances: are they normal/variable/words/bytes/weak, and how many instance variables does each instance have. "format" is a bit-field, so you need to wrangle bits to modify it.

What I'm going to test is what the VM does if I'm not careful and forget to update an instance of Class somewhere to be big enough to store my extra instance variables:
  1. Make a class, e.g. "TestVMCrash", with three instance variables, and a method, e.g. >>third, which sets the third instance variable.
  2. Get the format of that class: "TestVMCrash format", which returns 136 for me (which means "normal class, 3 instvars").
  3. Reduce the number of instance variables in TestVMCrash to 2.
  4. Make an instance and try to set the third, now non-existent, instance variable.
So after making the class, I reduce the number of instance variables:

ClassBuilder new computeFormat: #normal instSize: 2 forSuper: Object ccIndex: 0
" returns 134 "
TestVMCrash setFormat: 134. "The class now has only two instvars"

Now:

o := TestVMCrash new.
" o will have 2 instance varables, but here we try to set an non-existant third: "
o third.

This causes the VM to behave badly. The first time I tried, it crashed with a SEGFAULT. The second time, it froze. The VM barged ahead and corrupted the image, so there are no checks on invalid instance variable accesses.

In conclusion, I need to be very careful when adding instance variables to Class, and back up my image often.