Hi Stef,

On Wed, Feb 13, 2013 at 11:40 AM, St�phane Ducasse <stephane.ducasse@inria.fr> wrote:
I repost the mail to the mailing-list since I do not see it in the vm-dev

did you post to 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.

It doesn't matter what it returns as it's return value is always ignored. �It assigns to newMethod. �I suspect it returns currentClass because a) the return type was always sqInt because Slang didn't support void functions, and b) currentClass is a value in hand so probably in a register and hence cheap to return.
- what is the invariant?�
that currentclass always point to the currently looked up class and�
newMethod is the found method?

The input arguments are messageSelector, argumentCount and its argument, class. �The VM suffers somewhat from being cluttered with global variables, which is I think a legacy of the blue-book specification (the Smalltalk code that was used to implement Interpreter in VMMaker) being derived from the Alto and Dorado implementations in microcode. �It would be nicer if there were fewer variables, but e.g. supplying argumentCount as a parameter throughout all the message handling routines can be difficult, especially when things like perform: and MNU change the argumentCount during message send.

- why�lookupMethodFor: selector InDictionary: dictionary is defined in StackInterpreter but never used
only in CoInterpreter?

Well, it belongs in StackInterpreter and could be used in the other lookup methods. �I was probably considering rewriting the other lookup routines to use �lookupMethodFor:�InDictionary: but didn't get round to it.


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);
}








--
best,
Eliot