I repost the mail to the mailing-list since I do not see it in the vm-dev Stef
Hi
I was reading the following method in the VM code and I have a couple of questions:
- I do not understand why lookupMethodInClass: may return a class. I was thinking that it would return a method.
- what is the invariant? that currentclass always point to the currently looked up class and newMethod is the found method?
- why lookupMethodFor: selector InDictionary: dictionary is defined in StackInterpreter but never used only in CoInterpreter?
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); }