Thanks
lookupMethodInClass: class
| currentClass dictionary found |
<inline: false>
self assert: class ~= objectMemory nilObject.
currentClass := class.
[currentClass ~= objectMemory nilObject]
whileTrue:
[dictionary := objectMemory fetchPointer: MethodDictionaryIndex ofObject: currentClass.
*** trick with the cannotInterpret ***
dictionary = objectMemory nilObject ifTrue:
["MethodDict pointer is nil (hopefully due a swapped out stub)
-- raise exception #cannotInterpret:."
self createActualMessageTo: class.
messageSelector := objectMemory splObj: SelectorCannotInterpret.
self sendBreak: messageSelector + BaseHeaderSize
point: (objectMemory lengthOf: messageSelector)
receiver: nil.
^self lookupMethodInClass: (self superclassOf: currentClass)].
*** trick with the cannotInterpret end ***
found := self lookupMethodInDictionary: dictionary.
found ifTrue: [^currentClass].
^^^^^^^^^^^^^^^^^^^^^^^^^
currentClass := self superclassOf: currentClass].
"Could not find #doesNotUnderstand: -- unrecoverable error."
messageSelector = (objectMemory splObj: SelectorDoesNotUnderstand) ifTrue:
[self error: 'Recursive not understood error encountered'].
"Cound not find a normal message -- raise exception #doesNotUnderstand:"
self createActualMessageTo: class.
messageSelector := objectMemory splObj: SelectorDoesNotUnderstand.
self sendBreak: messageSelector + BaseHeaderSize
point: (objectMemory lengthOf: messageSelector)
receiver: nil.
^self lookupMethodInClass: class
if�(found) {
return�currentClass;
}
static sqInt
lookupMethodInClass(sqInt class)
{
// StackInterpreter>>#lookupMethodInClass: � DECL_MAYBE_SQ_GLOBAL_STRUCT
� � sqInt currentClass;
� � sqInt dictionary;
� � sqInt found;
� � sqInt header;
� � sqInt index;
� � sqInt length;
� � sqInt mask;
� � sqInt methodArray;
� � sqInt nextSelector;
� � sqInt sz;
� � sqInt wrapAround;
assert(class != (nilObject()));
currentClass = class;
while (currentClass != GIV(nilObj)) {
dictionary = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << ShiftForWord));
if (dictionary == GIV(nilObj)) {
/* ifTrue: */
createActualMessageTo(class);
GIV(messageSelector) = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorCannotInterpret << ShiftForWord));
sendBreakpointreceiver(GIV(messageSelector) + BaseHeaderSize, lengthOf(GIV(messageSelector)), null);
return lookupMethodInClass(longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << ShiftForWord)));
}
/* begin lookupMethodInDictionary: */
/* begin fetchWordLengthOf: */
/* begin sizeBitsOf: */
header = longAt(dictionary);
sz = ((header & TypeMask) == HeaderTypeSizeAndClass
? (longAt(dictionary - (BytesPerWord * 2))) & LongSizeMask
: header & SizeMask);
length = ((usqInt) (sz - BaseHeaderSize)) >> ShiftForWord;
mask = (length - SelectorStart) - 1;
/* messageSelector */
index = SelectorStart + (mask & (((GIV(messageSelector) & 1)
? (GIV(messageSelector) >> 1)
: (((usqInt) (longAt(GIV(messageSelector)))) >> HashBitsOffset) & HashMaskUnshifted)));
wrapAround = 0;
while (1) {
nextSelector = longAt((dictionary + BaseHeaderSize) + (index << ShiftForWord));
if (nextSelector == GIV(nilObj)) {
found = 0;
goto l1;
}
if (nextSelector == GIV(messageSelector)) {
methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
found = 1;
goto l1;
}
index += 1;
if (index == length) {
if (wrapAround) {
found = 0;
goto l1;
}
wrapAround = 1;
index = SelectorStart;
}
}
found = 0;
l1: /* end lookupMethodInDictionary: */;
if (found) {
return currentClass;
}
currentClass = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << ShiftForWord));
}
if (GIV(messageSelector) == (longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorDoesNotUnderstand << ShiftForWord)))) {
error("Recursive not understood error encountered");
}
createActualMessageTo(class);
GIV(messageSelector) = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorDoesNotUnderstand << ShiftForWord));
sendBreakpointreceiver(GIV(messageSelector) + BaseHeaderSize, lengthOf(GIV(messageSelector)), null);
return lookupMethodInClass(class);
}