Hello squeakers,
Of the long and exiting list of things that are in consideration for 3.9a, one is MethodAnnotations. This is a changeset that was done by Andreas long time ago (2002, I think) and it's used extensively in Tweak. At SCG, we have used it for ByteSurgeon and are using it for another ongoing project.
What are MethodAnnotations? ---------------------------------------
MethodAnnotations can be seen from two perspectives:
1) storing state in CompiledMethod objects.
In Squeak, CompiledMethod is a strange class. One thing you can't do is adding an instance variable. This makes experimentation awfully complicated, e.g. people made hacks to store state in the literalFrame or in class vars... see MethodWrappers for an example.
MethodAnnotations just provides a general, nice and easy way to store stuff in compiledMethods, no need for hacks anymore.
e.g. store:
(Object>>#halt) setProperty: #hello toValue: 5.
and read:
(Object>>#halt) valueOfProperty: #value;
2) Syntax for Method Annotations.
We can set annoations to methods using the syntax we already know for primitives (which are, in a sense, just an annotation):
Object>>mumble <hello: 4>
Tweak uses these annotations to describe when a method should be activated.
How are they implemented? -------------------------------------- Andreas' orginal implemention used a big WeakIdentityKeyDictionary in a class var of CompiledMethods to store the IdentityDictionary for each method. This turns out to have some nice properties (no space is used for non-annotated methods) and a bad one: Performance. For ByteSurgeon, after annotation all methods (40.000), it was unusably slow.
So we hacked a version that used the literealFrame instead, after discussing this with Andreas, we now use the second-last literal Frame entry. The reasoning is the following: The first one is already used for some primitives, the last one encodes the class in the case that there is a supersend in the method.
So if we use the last entry to store the class for each method (supered or not), we can put the annoations in the one before and don't need to test for anything. Putting the class (or Trait) in the last litereal has the nice side-effect of making a fast #who possible.
The changesets attached are a first step: We are right now adding the class binding to all methods but quickmethods (need to fix that), the second last literal is initialized with nil and will lazy initalize the property dictionary if it's accessed.
Please note that the attached changesets need to be files in in-order and the first one will recompile the whole image.
Filling the last literal with the class (or trait) for all methods will be done in an addional step after the annotation cs is in 3.9. Then we will change the implementation of compiledMethod>>who to use this information.
Any comments? Does anyone see a problem with the annotations itself or the implementation?
Marcus