Hi All,
I just got a little burned. I was searching through an Array of
symbols and integers (it is the PrimitiveTable from the VM), wanting to
filter-out methods with a with a certain pragma. The code looks like:
anArray doWithIndex:
[:entry :index|
(self whichClassIncludesSelector: entry) ifNotNil:
[:c| | m |
m := c >> entry.
(m pragmaAt: #option:) ifNotNil:
[:pragma|
(initializationOptions at: (pragma arguments first) ifAbsent: [true])
ifFalse:
[anArray at: index put: 0]]]]
the error was a keyNotFound error for c >> entry. Turns out entry was the
integer 306, a code for a quick primitive that returns some inst var. The
question is why did (self whichClassIncludesSelector: entry) evaluate to
other than nil given that 306 is /not/ a selector in any of the classes
from self on up. Well, it's MethodDictionary's use of pointsTo: that is at
fault:
MethodDictionary>>includesKey: aSymbol
"This override assumes that pointsTo is a fast primitive"
aSymbol ifNil: [^ false].
^ self pointsTo: aSymbol
ProtoObject>>pointsTo: anObject
"This method returns true if self contains a pointer to anObject,
and returns false otherwise"
<primitive: 132>
1 to: self class instSize do:
[:i | (self instVarAt: i) == anObject ifTrue: [^ true]].
1 to: self basicSize do:
[:i | (self basicAt: i) == anObject ifTrue: [^ true]].
^ false
Turns out that 306 was the tally of one of the method dictionaries along
self's superclass chain. This seems to be to be completely bogus. Do we
really need crude performance hacks like this any more?
--
best,
Eliot