[Vm-dev] [commit][3429] CogVM source as per VMMaker.oscog-eem.1446

commits at squeakvm.org commits at squeakvm.org
Mon Aug 31 21:10:07 UTC 2015


Revision: 3429
Author:   eliot
Date:     2015-08-31 14:10:05 -0700 (Mon, 31 Aug 2015)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.1446

Spur:
Implement ephemeron queue primitive.  Add an image flag that controls the
finalization support (StackInterpreter instVar newFinalization).  If unset,
finalization is as currently expected; WeakArray finalizes all WeakArrays in
its registries on each finalization (which does not scale!).  If set, then both
fired ephemerons and bereaved weak arrays are added to the finalization queue
and the finalization semaphore is signalled.  In this regime the image is
expected to send mourn to each element of the queue, and weak arrays will send
themselves finalize in mourn, side-stepping the finalizeValues steps and
rendering WeakArray's FinalizationDependents and WeakRegistry obsolete.
The bit is set via
    Smalltalk vmParameterAt: 48
              put: ((Smalltalk vmParameterAt: 48) bitOr: 64).

Rename ephemeronQueue to mournQueue to reflect more general use of the queue.

ThreadedFFIPlugin
Added ThreadedFFIPlugin>>#primitiveLoadSymbolFromModule (copy and adapt from
IA32ABIPlugin).

Newspeak:
Fix bug from refactoring in VMMaker.oscog-eem.1438 -
lookupProtected:startingAt:rule: should return the actual lookup rule, not 0.

Rename local variable lookupClass to currentClass in a few places to avoid
confusion with instance variable lkupClass.

The actual receiver of an MNU from an outer send is not necessarily the method
receiver:

Fix bug in MNU for cogged dynamic super sends - should start looking for
#doesNotUnderstand: in the superclass not the receiver class. Unify MNU
lookup between absent and present receiver sends as a result.

Further fix outer send MNU by not confusing lkupClass and lkupClassTag.
Push setting lkupClassTag down to clarify it is for new cache entries.

Modified Paths:
--------------
    branches/Cog/nsspursrc/vm/cogit.h
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspurstack64src/vm/gcc3x-interp.c
    branches/Cog/nsspurstack64src/vm/interp.c
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/spursistasrc/vm/cogit.h
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/cogit.h
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spurstack64src/vm/gcc3x-interp.c
    branches/Cog/spurstack64src/vm/interp.c
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.c
    branches/Cog/src/plugins/SqueakFFIPrims/ARM32FFIPlugin.c
    branches/Cog/src/plugins/SqueakFFIPrims/IA32FFIPlugin.c
    branches/Cog/src/vm/cogit.h
    branches/Cog/src/vm/cointerp.c
    branches/Cog/src/vm/cointerp.h
    branches/Cog/src/vm/cointerpmt.c
    branches/Cog/src/vm/cointerpmt.h
    branches/Cog/src/vm/gcc3x-cointerp.c
    branches/Cog/src/vm/gcc3x-cointerpmt.c
    branches/Cog/stacksrc/vm/gcc3x-interp.c
    branches/Cog/stacksrc/vm/interp.c

Property Changed:
----------------
    branches/Cog/platforms/Cross/vm/sqSCCSVersion.h

Modified: branches/Cog/nsspursrc/vm/cogit.h
===================================================================
--- branches/Cog/nsspursrc/vm/cogit.h	2015-08-22 16:40:42 UTC (rev 3428)
+++ branches/Cog/nsspursrc/vm/cogit.h	2015-08-31 21:10:05 UTC (rev 3429)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1441 uuid: c41d605b-7d2e-4ecc-95e1-b295119106a7
+	CCodeGenerator VMMaker.oscog-eem.1446 uuid: 9ab44a24-1f54-4c21-b99a-3977d5ecc0a1
  */
 
 

Modified: branches/Cog/nsspursrc/vm/cointerp.c
===================================================================
--- branches/Cog/nsspursrc/vm/cointerp.c	2015-08-22 16:40:42 UTC (rev 3428)
+++ branches/Cog/nsspursrc/vm/cointerp.c	2015-08-31 21:10:05 UTC (rev 3429)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1441 uuid: c41d605b-7d2e-4ecc-95e1-b295119106a7
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1446 uuid: 9ab44a24-1f54-4c21-b99a-3977d5ecc0a1
    from
-	CoInterpreter VMMaker.oscog-eem.1441 uuid: c41d605b-7d2e-4ecc-95e1-b295119106a7
+	CoInterpreter VMMaker.oscog-eem.1446 uuid: 9ab44a24-1f54-4c21-b99a-3977d5ecc0a1
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1441 uuid: c41d605b-7d2e-4ecc-95e1-b295119106a7 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1446 uuid: 9ab44a24-1f54-4c21-b99a-3977d5ecc0a1 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -221,7 +221,6 @@
 #if !defined(EnforceAccessControl) /* Allow EnforceAccessControl to be overridden on the compiler command line */
 # define EnforceAccessControl 1
 #endif
-#define EphemeronQueueRootIndex 4098
 #define ExcessSignalsIndex 2
 #define ExternalObjectsArray 38
 #define ExtraRootsSize 2048
@@ -293,6 +292,7 @@
 #define MillisecondClockMask 0x1FFFFFFF
 #define MinBackwardJumpCountForCompile 40
 #define MixinIndex 3
+#define MournQueueRootIndex 4098
 #define MULTIPLEBYTECODESETS 1
 #define MyListIndex 3
 #define NewspeakVM 1
@@ -701,6 +701,7 @@
 extern sqInt primitiveFail(void);
 extern sqInt primitiveFailFor(sqInt reasonCode);
 extern sqInt primitiveFailureCode(void);
+static void primitiveFetchNextMourner(void);
 static void primitiveFloatAdd(void);
 static void primitiveFloatAt(void);
 static void primitiveFloatAtPut(void);
@@ -1188,6 +1189,7 @@
 static sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron) NoDbgRegParms;
 extern void pushRemappableOop(sqInt oop);
 static sqInt pushonObjStack(sqInt objOop, sqInt objStack) NoDbgRegParms;
+static void queueMourner(sqInt anEphemeronOrWeakArray) NoDbgRegParms;
 static sqInt rawHashBitsOf(sqInt objOop) NoDbgRegParms;
 static void rebuildFreeListsForPigCompact(void);
 extern sqInt remapObj(sqInt objOop);
@@ -1380,13 +1382,13 @@
 extern void loadInitialContext(void);
 extern void longPrintOop(sqInt oop);
 extern sqInt longStoreBytecodeForHeader(sqInt methodHeader);
-static sqInt lookupDnuPresent(void);
 static sqInt lookupInMethodCacheSelclassTag(sqInt selector, sqInt classTag) NoDbgRegParms;
 static sqInt lookupLexicalfromrule(sqInt selector, sqInt mixin, sqInt rule) NoDbgRegParms;
 static sqInt lookupMethodInClass(sqInt class) NoDbgRegParms;
+static sqInt lookupMNU(void);
 static sqInt lookupMNUInClass(sqInt class) NoDbgRegParms;
 static sqInt lookupOrdinaryNoMNUEtcInClass(sqInt class) NoDbgRegParms;
-static void lookupOrdinarySend(void);
+static sqInt lookupOrdinarySend(void);
 static sqInt lookupProtectedstartingAtrule(sqInt selector, sqInt mixinApplication, sqInt rule) NoDbgRegParms;
 extern sqInt lookupSelectorinClass(sqInt selector, sqInt class);
 extern sqInt makePointwithxValueyValue(sqInt xValue, sqInt yValue);
@@ -1554,7 +1556,6 @@
 static void primitiveInstVarAt(void);
 static void primitiveInstVarAtPut(void);
 EXPORT(sqInt) primitiveLongRunningPrimitive(void);
-EXPORT(sqInt) primitiveMakeEphemeron(void);
 static void primitiveObjectPointsTo(void);
 static void primitivePerform(void);
 static void primitivePin(void);
@@ -1585,8 +1586,8 @@
 _iss usqInt freeStart;
 _iss sqInt specialObjectsOop;
 _iss sqInt argumentCount;
-_iss sqInt messageSelector;
 _iss sqInt bytecodeSetSelector;
+_iss sqInt messageSelector;
 _iss usqInt instructionPointer;
 _iss usqInt newMethod;
 _iss sqInt markStack;
@@ -1649,10 +1650,11 @@
 _iss sqInt extraRootCount;
 _iss sqInt growHeadroom;
 _iss sqInt invalidObjStackPage;
-_iss sqInt methodDictLinearSearchLimit;
 _iss sqInt previousRememberedSetSize;
 _iss sqInt classNameIndex;
-_iss sqInt ephemeronQueue;
+_iss sqInt methodDictLinearSearchLimit;
+_iss sqInt pendingFinalizationSignals;
+_iss sqInt mournQueue;
 _iss sqInt tenureCriterion;
 _iss sqInt metaclassNumSlots;
 _iss sqInt preemptionYields;
@@ -1667,6 +1669,7 @@
 _iss sqInt highestRunnableProcessPriority;
 _iss usqLong longRunningPrimitiveStartUsecs;
 _iss usqLong longRunningPrimitiveStopUsecs;
+_iss sqInt newFinalization;
 _iss usqLong statCheckForEvents;
 _iss usqLong statGCEndUsecs;
 _iss sqInt weakList;
@@ -1675,12 +1678,10 @@
 _iss sqInt firstSegmentSize;
 _iss usqLong gcStartUsecs;
 _iss usqInt lowSpaceThreshold;
-_iss sqInt noThreadingOfGUIThread;
-_iss sqInt pendingFinalizationSignals;
-_iss sqInt processHasThreadId;
 _iss sqInt rememberedSetLimit;
 _iss sqInt shrinkThreshold;
 _iss usqLong statIOProcessEvents;
+_iss sqInt imageHeaderFlags;
 _iss sqInt lastHash;
 _iss sqInt lastMethodCacheProbeWrite;
 _iss sqInt longRunningPrimitiveCheckSequenceNumber;
@@ -1727,7 +1728,6 @@
 _iss sqInt tenuringProportion;
 _iss sqInt classByteArrayCompactIndex;
 _iss sqInt gcSemaphoreIndex;
-_iss sqInt imageHeaderFlags;
 _iss usqLong longRunningPrimitiveGCUsecs;
 _iss sqInt overflowLimit;
 _iss StackPage * overflowedPage;
@@ -1977,7 +1977,7 @@
 	/* 169 */ primitiveNotIdentical,
 	/* 170 */ primitiveAsCharacter,
 	/* 171 */ primitiveImmediateAsInteger,
-	/* 172 */ (void (*)(void))0,
+	/* 172 */ primitiveFetchNextMourner,
 	/* 173 */ primitiveSlotAt,
 	/* 174 */ primitiveSlotAtPut,
 	/* 175 */ primitiveBehaviorHash,
@@ -2414,7 +2414,7 @@
 /*560*/	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0,-1,-1
 	};
 char expensiveAsserts = 0;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1441";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1446";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -13689,7 +13689,7 @@
 					GIV(localAbsentReceiverOrZero) = 0;
 					GIV(localAbsentReceiver) = methodReceiver;
 
-					/* For use by MNU */
+					/* MNU lookup starts here. */
 
 					GIV(lkupClass) = (((tagBits1 = methodReceiver & 3)) != 0
 						? longAt((GIV(classTableFirstPage) + BaseHeaderSize) + (tagBits1 << (shiftForWord())))
@@ -16717,7 +16717,6 @@
 	else {
 		assert(!((isOopForwarded(GIV(messageSelector)))));
 		assert(!((isForwardedClassTag(methodReceiverClassTag))));
-		GIV(lkupClassTag) = methodReceiverClassTag;
 		/* begin lookupDynamicSuperSendNoMNU: */
 		GIV(localAbsentReceiver) = methodReceiver;
 		GIV(localAbsentReceiverOrZero) = 0;
@@ -16735,10 +16734,12 @@
 		errSelIdx = lookupProtectedNoMNUstartingAtrule(GIV(messageSelector), GIV(lkupClass), LookupRuleDynamicSuper);
 		if (errSelIdx != 0) {
 			assert(errSelIdx == SelectorDoesNotUnderstand);
-			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, classAtIndex(methodReceiverClassTag));
+			assert(GIV(localAbsentReceiver) == methodReceiver);
+			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, GIV(lkupClass));
 			/* begin unreachable */
 			error("UNREACHABLE");
 		}
+		GIV(lkupClassTag) = methodReceiverClassTag;
 		addNewMethodToNSCache(LookupRuleDynamicSuper);
 	}
 	if (((GIV(newMethod) & 3) == 0)
@@ -16880,7 +16881,6 @@
 	else {
 		assert(!((isOopForwarded(GIV(messageSelector)))));
 		assert(!((isForwardedClassTag(methodReceiverClassTag))));
-		GIV(lkupClassTag) = methodReceiverClassTag;
 		/* begin lookupImplicitReceiverSendNoMNU: */
 		GIV(messageSelector) = (((GIV(messageSelector) & 3) == 0)
 		 && (((longAt(GIV(messageSelector))) & 0x3FFFFF) == 8)
@@ -17042,10 +17042,12 @@
 	l1:	/* end lookupImplicitReceiverSendNoMNU: */;
 		if (errSelIdx != 0) {
 			assert(errSelIdx == SelectorDoesNotUnderstand);
-			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, classAtIndex(methodReceiverClassTag));
+			assert(GIV(localAbsentReceiver) == methodReceiver);
+			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, GIV(lkupClass));
 			/* begin unreachable */
 			error("UNREACHABLE");
 		}
+		GIV(lkupClassTag) = methodReceiverClassTag;
 		addNewMethodToNSCache(LookupRuleImplicit);
 	}
 	longAtput(GIV(stackPointer) + ((GIV(argumentCount) + 1) * BytesPerWord), GIV(localAbsentReceiver));
@@ -17611,14 +17613,18 @@
 	else {
 		assert(!((isOopForwarded(GIV(messageSelector)))));
 		assert(!((isForwardedClassTag(methodReceiverClassTag))));
-		GIV(lkupClassTag) = methodReceiverClassTag;
 		errSelIdx = lookupOuterSendNoMNUdepth(methodReceiver, depth);
 		if (errSelIdx != 0) {
 			assert(errSelIdx == SelectorDoesNotUnderstand);
-			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, classAtIndex(methodReceiverClassTag));
+			longAtput(GIV(stackPointer) + ((GIV(argumentCount) + 1) * BytesPerWord), GIV(localAbsentReceiver));
+			handleMNUInMachineCodeToclassForMessage(errSelIdx, GIV(localAbsentReceiver), GIV(lkupClass));
 			/* begin unreachable */
 			error("UNREACHABLE");
 		}
+
+		/* Successful lookup cached under the sender's class */
+
+		GIV(lkupClassTag) = methodReceiverClassTag;
 		addNewMethodToNSCache(depth);
 	}
 	longAtput(GIV(stackPointer) + ((GIV(argumentCount) + 1) * BytesPerWord), GIV(localAbsentReceiver));
@@ -17770,14 +17776,15 @@
 	else {
 		assert(!((isOopForwarded(GIV(messageSelector)))));
 		assert(!((isForwardedClassTag(methodReceiverClassTag))));
-		GIV(lkupClassTag) = methodReceiverClassTag;
 		errSelIdx = lookupOuterSendNoMNUdepth(methodReceiver, 0);
 		if (errSelIdx != 0) {
 			assert(errSelIdx == SelectorDoesNotUnderstand);
-			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, classAtIndex(methodReceiverClassTag));
+			assert(GIV(localAbsentReceiver) == methodReceiver);
+			handleMNUInMachineCodeToclassForMessage(errSelIdx, methodReceiver, GIV(lkupClass));
 			/* begin unreachable */
 			error("UNREACHABLE");
 		}
+		GIV(lkupClassTag) = methodReceiverClassTag;
 		addNewMethodToNSCache(LookupRuleSelf);
 	}
 	if (((GIV(newMethod) & 3) == 0)
@@ -20285,7 +20292,7 @@
 		receiverClass = fetchClassOfNonImm(GIV(localAbsentReceiver));
 	}
 
-	/* For use by MNU */
+	/* MNU lookup starts here. */
 
 	GIV(lkupClass) = receiverClass;
 	mixinApplication = findApplicationOfTargetMixinstartingAtBehavior(mixin, receiverClass);
@@ -20582,12 +20589,12 @@
 static sqInt
 lookupProtectedNoMNUstartingAtrule(sqInt selector, sqInt mixinApplication, sqInt rule)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt currentClass;
     sqInt dictionary;
     sqInt found;
     sqInt hash;
     sqInt index;
     usqInt length;
-    sqInt lookupClass;
     usqInt mask;
     sqInt methodArray;
     sqInt nextSelector;
@@ -20601,13 +20608,13 @@
     sqInt objOop5;
     sqInt wrapAround;
 
-	lookupClass = mixinApplication;
-	while (!(lookupClass == GIV(nilObj))) {
+	currentClass = mixinApplication;
+	while (!(currentClass == GIV(nilObj))) {
 		/* begin followObjField:ofObject: */
-		objOop = longAt((lookupClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
+		objOop = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
 		assert(isNonImmediate(objOop));
 		if (((longAt(objOop)) & (0x3FFFFF - 8)) == 0) {
-			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, lookupClass, objOop);
+			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, currentClass, objOop);
 		}
 		dictionary = objOop;
 		/* begin lookupMethodInDictionary: */
@@ -20722,12 +20729,12 @@
 			return 0;
 		}
 		/* begin followField:ofObject: */
-		objOop1 = longAt((lookupClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
+		objOop1 = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
 		if (((objOop1 & 3) == 0)
 		 && (((longAt(objOop1)) & 0x3FFFFF) == 8)) {
-			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, lookupClass, objOop1);
+			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, currentClass, objOop1);
 		}
-		lookupClass = objOop1;
+		currentClass = objOop1;
 	}
 	return SelectorDoesNotUnderstand;
 }
@@ -25437,10 +25444,9 @@
 	GIV(imageFloatsBigEndian) = ((headerFlags & 2) == 0
 		? 1
 		: 0);
-	GIV(processHasThreadId) = (headerFlags & 4) != 0;
 	GIV(flagInterpretedMethods) = (headerFlags & 8) != 0;
 	GIV(preemptionYields) = (headerFlags & 16) == 0;
-	GIV(noThreadingOfGUIThread) = (headerFlags & 32) != 0;
+	GIV(newFinalization) = (headerFlags & 64) != 0;
 	
 	/* begin getWord32FromFile:swap: */
 	w8 = 0;
@@ -32314,7 +32320,7 @@
     usqInt newObj;
     usqInt numBytes;
     sqInt numSlots;
-    sqInt s;
+    usqInt s;
     char *sp;
     sqInt sz;
 
@@ -34341,6 +34347,24 @@
 	return GIV(primFailCode);
 }
 
+	/* InterpreterPrimitives>>#primitiveFetchNextMourner */
+static void
+primitiveFetchNextMourner(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt mourner;
+    char *sp;
+
+	mourner = popObjStack(GIV(mournQueue));
+	if (mourner == null) {
+		GIV(primFailCode) = PrimErrNotFound;
+	}
+	else {
+		/* begin pop:thenPush: */
+		longAtput((sp = GIV(stackPointer) + ((1 - 1) * BytesPerWord)), mourner);
+		GIV(stackPointer) = sp;
+	}
+}
+
 	/* InterpreterPrimitives>>#primitiveFloatAdd */
 static void
 primitiveFloatAdd(void)
@@ -37991,7 +38015,7 @@
     sqInt err;
     sqInt hash;
     sqInt instSpec;
-    sqInt newObj;
+    usqInt newObj;
     usqInt newObj1;
     usqInt numBytes;
     sqInt numSlots;
@@ -38117,7 +38141,7 @@
     sqInt i;
     usqInt instSpec;
     sqInt literalCount;
-    sqInt newObj;
+    usqInt newObj;
     usqInt newObj1;
     usqInt numBytes;
     sqInt numSlots;
@@ -44016,7 +44040,7 @@
     sqInt fillValue;
     sqInt hash;
     usqInt instSpec;
-    sqInt newObj;
+    usqInt newObj;
     usqInt newObj1;
     usqInt numBytes;
     usqInt numSlots;
@@ -45112,11 +45136,10 @@
 			assert(isEphemeron(ephemeron));
 			assert(!(isScavengeSurvivor(keyOfEphemeron(ephemeron))));
 			/* begin fireEphemeron: */
-			/* begin queueEphemeron: */
-			assert((isNonImmediate(ephemeron))
-			 && ((formatOf(ephemeron)) == (ephemeronFormat())));
-			pushonObjStack(ephemeron, GIV(ephemeronQueue));
+			queueMourner(ephemeron);
+			/* begin signalFinalization: */
 			forceInterruptCheck();
+			GIV(pendingFinalizationSignals) += 1;
 			/* begin storePointerUnchecked:ofObject:withValue: */
 			valuePointer = copyAndForward(keyOfEphemeron(ephemeron));
 			assert(!(isForwarded(ephemeron)));
@@ -45167,11 +45190,10 @@
 			ephemeron1 = referent;
 			assert(!(isScavengeSurvivor(keyOfEphemeron(ephemeron1))));
 			/* begin fireEphemeron: */
-			/* begin queueEphemeron: */
-			assert((isNonImmediate(ephemeron1))
-			 && ((formatOf(ephemeron1)) == (ephemeronFormat())));
-			pushonObjStack(ephemeron1, GIV(ephemeronQueue));
+			queueMourner(ephemeron1);
+			/* begin signalFinalization: */
 			forceInterruptCheck();
+			GIV(pendingFinalizationSignals) += 1;
 			/* begin storePointerUnchecked:ofObject:withValue: */
 			valuePointer1 = copyAndForward(keyOfEphemeron(ephemeron1));
 			assert(!(isForwarded(ephemeron1)));
@@ -45260,7 +45282,7 @@
 
 /*	Process a weak survivor on the weakList. Those of its fields
 	which have not survived the scavenge should be nilled, and if any
-	are, the coInterpreter should be informed via signalFinalization:.
+	are, the coInterpreter should be informed via fireFinalization:.
 	Answer if the weakObj has any young referents. */
 
 	/* SpurGenerationScavenger>>#processWeakSurvivor: */
@@ -45328,6 +45350,10 @@
 		}
 	}
 	if (weakObjShouldMourn) {
+		/* begin fireFinalization: */
+		if (GIV(newFinalization)) {
+			queueMourner(weakObj);
+		}
 		/* begin signalFinalization: */
 		forceInterruptCheck();
 		GIV(pendingFinalizationSignals) += 1;
@@ -46148,7 +46174,7 @@
     sqInt entry;
     sqInt expectedIndex;
     sqInt expectedIndex1;
-    sqInt freeChunk;
+    usqInt freeChunk;
     sqInt i;
     sqInt i1;
     sqInt index;
@@ -46187,7 +46213,7 @@
     sqInt ptr1;
     sqInt ptr2;
     sqInt slotBytes;
-    sqInt smallObj;
+    usqInt smallObj;
     sqInt start;
 
 	classIndex = (long32At(aClass + 4)) & 0x3FFFFF;
@@ -49129,7 +49155,7 @@
     sqInt fmt;
     sqInt hasYoung;
     sqInt i;
-    sqInt newObj;
+    usqInt newObj;
     usqInt newObj1;
     usqInt numBytes;
     usqInt numSlots;
@@ -49874,7 +49900,7 @@
 	/* begin followForwardedObjStacks */
 	followForwardedInObjStackatIndex(GIV(markStack), MarkStackRootIndex);
 	followForwardedInObjStackatIndex(GIV(weaklingStack), WeaklingStackRootIndex);
-	followForwardedInObjStackatIndex(GIV(ephemeronQueue), EphemeronQueueRootIndex);
+	followForwardedInObjStackatIndex(GIV(mournQueue), MournQueueRootIndex);
 	mapInterpreterOops();
 	/* begin followRememberedForwardersAndForgetFreeObjectsForPigCompact */
 	index = 0;
@@ -50290,8 +50316,8 @@
 		case WeaklingStackRootIndex:
 			GIV(weaklingStack) = freeOrNewPage;
 			break;
-		case EphemeronQueueRootIndex:
-			GIV(ephemeronQueue) = freeOrNewPage;
+		case MournQueueRootIndex:
+			GIV(mournQueue) = freeOrNewPage;
 			break;
 		default:
 			error("Case not found and no otherwise clause");
@@ -51126,8 +51152,8 @@
 		case WeaklingStackRootIndex:
 			GIV(weaklingStack) = stackOrNil;
 			break;
-		case EphemeronQueueRootIndex:
-			GIV(ephemeronQueue) = stackOrNil;
+		case MournQueueRootIndex:
+			GIV(mournQueue) = stackOrNil;
 			break;
 		default:
 			error("Case not found and no otherwise clause");
@@ -52246,7 +52272,7 @@
 l1:	/* end setHiddenRootsObj: */;
 	GIV(markStack) = swizzleObjStackAt(MarkStackRootIndex);
 	GIV(weaklingStack) = swizzleObjStackAt(WeaklingStackRootIndex);
-	GIV(ephemeronQueue) = swizzleObjStackAt(EphemeronQueueRootIndex);
+	GIV(mournQueue) = swizzleObjStackAt(MournQueueRootIndex);
 	assert(validObjStacks());
 	assert(isEmptyObjStack(GIV(markStack)));
 	assert(isEmptyObjStack(GIV(weaklingStack)));
@@ -53471,7 +53497,7 @@
     sqInt hash;
     sqInt i;
     sqInt iLimiT;
-    sqInt loadedObjectsArray;
+    usqInt loadedObjectsArray;
     sqInt mappedOop;
     usqInt newObj;
     usqInt numBytes;
@@ -55612,7 +55638,7 @@
 	/* begin markAndTraceHiddenRoots */
 	markAndTraceObjStackandContents(GIV(markStack), 0);
 	markAndTraceObjStackandContents(GIV(weaklingStack), 0);
-	markAndTraceObjStackandContents(GIV(ephemeronQueue), 1);
+	markAndTraceObjStackandContents(GIV(mournQueue), 1);
 	setIsMarkedOfto(longAt((GIV(hiddenRootsObj) + BaseHeaderSize) + (RememberedSetRootIndex << (shiftForWord()))), 1);
 	setIsMarkedOfto(freeListsObj(), 1);
 	if (((((usqInt) (longAt(GIV(classTableFirstPage)))) >> 24) & 0x1F) == 4) {
@@ -59561,7 +59587,6 @@
 static void
 markWeaklingsAndMarkAndFireEphemerons(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt anEphemeron;
     sqInt contextSize;
     sqInt contextSize1;
     sqInt contextSize2;
@@ -59627,6 +59652,7 @@
     sqInt sp2;
     sqInt topIndex;
     sqInt weakling;
+    sqInt weakReferenceOop;
 
 	numStrongSlots = 0;
 	numStrongSlots1 = 0;
@@ -59933,13 +59959,13 @@
 			assert(!(noUnscannedEphemerons()));
 			assert(allUnscannedEphemeronsAreActive());
 			for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerWord); p += 1) {
-				/* begin queueEphemeron: */
-				anEphemeron = longAt(p);
-				assert((isNonImmediate(anEphemeron))
-				 && ((formatOf(anEphemeron)) == (ephemeronFormat())));
-				pushonObjStack(anEphemeron, GIV(ephemeronQueue));
+				/* begin fireEphemeron: */
+				queueMourner(longAt(p));
+				/* begin signalFinalization: */
+				weakReferenceOop = longAt(p);
+				forceInterruptCheck();
+				GIV(pendingFinalizationSignals) += 1;
 			}
-			forceInterruptCheck();
 		}
 		/* begin markAllUnscannedEphemerons */
 		assert(!(noUnscannedEphemerons()));
@@ -60536,7 +60562,7 @@
     usqInt prevFree;
     usqInt prevFreeChunk;
     usqInt prevPrevFree;
-    usqInt prevPrevFreeChunk;
+    sqInt prevPrevFreeChunk;
     sqInt slotBytes;
     sqInt slotBytes1;
     usqInt there;
@@ -60976,6 +61002,10 @@
 			}
 			anyUnmarked = anyUnmarked1;
 			if (anyUnmarked) {
+				/* begin fireFinalization: */
+				if (GIV(newFinalization)) {
+					queueMourner(weakling);
+				}
 				/* begin signalFinalization: */
 				forceInterruptCheck();
 				GIV(pendingFinalizationSignals) += 1;
@@ -61790,8 +61820,8 @@
 		case WeaklingStackRootIndex:
 			GIV(weaklingStack) = nextPage;
 			break;
-		case EphemeronQueueRootIndex:
-			GIV(ephemeronQueue) = nextPage;
+		case MournQueueRootIndex:
+			GIV(mournQueue) = nextPage;
 			break;
 		default:
 			error("Case not found and no otherwise clause");
@@ -63286,6 +63316,30 @@
 	return noCheckPushonObjStack(objOop, objStack);
 }
 
+
+/*	Add the ephemeron to the queue and make it non-ephemeral, to avoid
+	subsequent firing.
+	Alas this means that other ephemerons on the same object not identified in
+	this sccavenge
+	or GC will not fire until later. But that's life. */
+
+	/* SpurMemoryManager>>#queueMourner: */
+static void
+queueMourner(sqInt anEphemeronOrWeakArray)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+	assert((isNonImmediate(anEphemeronOrWeakArray))
+	 && (((formatOf(anEphemeronOrWeakArray)) == (ephemeronFormat()))
+	 || ((formatOf(anEphemeronOrWeakArray)) == (weakArrayFormat()))));
+	assert(!((isonObjStack(anEphemeronOrWeakArray, GIV(mournQueue)))));
+	pushonObjStack(anEphemeronOrWeakArray, GIV(mournQueue));
+	if (((((usqInt) (longAt(anEphemeronOrWeakArray))) >> 24) & 0x1F) == 5) {
+		/* begin setFormatOf:to: */
+		assert(((1 >= 0) && (1 <= (formatMask()))));
+		flag("endianness");
+		longAtput(anEphemeronOrWeakArray, ((longAt(anEphemeronOrWeakArray)) & ((unsigned int)~(0x1F << 24))) + (1 << 24));
+	}
+}
+
 	/* SpurMemoryManager>>#rawHashBitsOf: */
 static sqInt
 rawHashBitsOf(sqInt objOop)
@@ -63895,8 +63949,8 @@
     sqInt prevPrevObj;
     sqInt prevPrevObj1;
     sqInt ptr;
-    sqInt savedInHashes;
-    sqInt savedOutHashes;
+    usqInt savedInHashes;
+    usqInt savedOutHashes;
     sqInt segAddr;
     sqInt segStart;
     sqInt slotBytes;
@@ -64372,7 +64426,7 @@
     sqInt formatField;
     sqInt len;
     usqInt newObj;
-    sqInt newString;
+    usqInt newString;
     usqInt numBytes;
     sqInt numSlots;
 
@@ -64884,8 +64938,8 @@
 	 || (isValidObjStack(GIV(markStack))))
 	 && (((GIV(weaklingStack) == GIV(nilObj))
 	 || (isValidObjStack(GIV(weaklingStack))))
-	 && ((GIV(ephemeronQueue) == GIV(nilObj))
-	 || (isValidObjStack(GIV(ephemeronQueue)))));
+	 && ((GIV(mournQueue) == GIV(nilObj))
+	 || (isValidObjStack(GIV(mournQueue)))));
 }
 
 
@@ -65082,7 +65136,7 @@
 bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil)
 {
     usqInt bridgeSpan;
-    sqInt clifton;
+    usqInt clifton;
     usqInt segEnd;
 
 	segEnd = ((aSegment->segSize)) + ((aSegment->segStart));
@@ -65323,7 +65377,7 @@
     sqInt largeChild;
     sqInt newEndOfMemory;
     sqInt next;
-    sqInt node;
+    usqInt node;
     SpurSegmentInfo *seg;
     sqInt smallChild;
     sqInt treeNode;
@@ -65427,7 +65481,7 @@
 static sqInt
 readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    usqInt bridge;
+    sqInt bridge;
     usqInt bridgehead;
     usqInt bridgeSpan;
     sqInt bytesRead;
@@ -65643,7 +65697,7 @@
     usqLong firstSavedBridgeWord;
     sqInt nWritten;
     usqInt pier1;
-    sqInt pier2;
+    usqInt pier2;
     usqLong secondSavedBridgeWord;
 
 	pier1 = (((segment->segSize)) + ((segment->segStart))) - (2 * BaseHeaderSize);
@@ -70567,171 +70621,6 @@
 }
 
 
-/*	A present receiver send lookup failed. Replace the arguments on the stack
-	with a Message and lookup #doesNotUndestand:.
-	IN: lkupClass
-	IN: messageSelector
-	IN: argumentCount
-	OUT: newMethod
-	OUT: primitiveIndex
-	RESULT: LookupRuleMNU */
-
-	/* StackInterpreter>>#lookupDnuPresent */
-static sqInt
-lookupDnuPresent(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt currentClass;
-    sqInt dictionary;
-    sqInt found;
-    sqInt hash;
-    sqInt index;
-    usqInt length;
-    usqInt mask;
-    sqInt methodArray;
-    sqInt nextSelector;
-    usqInt numSlots;
-    sqInt objOop;
-    sqInt objOop1;
-    sqInt objOop11;
-    sqInt objOop2;
-    sqInt objOop3;
-    sqInt objOop4;
-    sqInt objOop5;
-    sqInt wrapAround;
-
-	createActualMessageTo(GIV(lkupClass));
-	GIV(messageSelector) = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorDoesNotUnderstand << (shiftForWord())));
-	currentClass = GIV(lkupClass);
-	while (currentClass != GIV(nilObj)) {
-		/* begin followObjField:ofObject: */
-		objOop = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
-		assert(isNonImmediate(objOop));
-		if (((longAt(objOop)) & (0x3FFFFF - 8)) == 0) {
-			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, currentClass, objOop);
-		}
-		dictionary = objOop;
-		/* begin lookupMethodInDictionary: */
-		/* begin numSlotsOf: */
-		flag("endianness");
-		assert((classIndexOf(dictionary)) > (isForwardedObjectClassIndexPun()));
-		numSlots = byteAt(dictionary + 7);
-		length = (numSlots == 0xFF
-			? longAt(dictionary - BaseHeaderSize)
-			: numSlots);
-
-		/* Use linear search on small dictionaries; its cheaper.
-		   Also the limit can be set to force linear search of all dictionaries, which supports the
-		   booting of images that need rehashing (e.g. because a tracer has generated an image
-		   with different hashes but hasn't rehashed it yet.) */
-
-		mask = (length - SelectorStart) - 1;
-		if (mask <= GIV(methodDictLinearSearchLimit)) {
-			index = 0;
-			while (index <= mask) {
-				nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << (shiftForWord())));
-				if (((nextSelector & 3) == 0)
-				 && (((longAt(nextSelector)) & 0x3FFFFF) == 8)) {
-					nextSelector = fixFollowedFieldofObjectwithInitialValue(index + SelectorStart, dictionary, nextSelector);
-				}
-				if (nextSelector == GIV(messageSelector)) {
-					/* begin followObjField:ofObject: */
-					objOop5 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
-					assert(isNonImmediate(objOop5));
-					if (((longAt(objOop5)) & (0x3FFFFF - 8)) == 0) {
-						objOop5 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop5);
-					}
-					methodArray = objOop5;
-					/* begin followField:ofObject: */
-					objOop11 = longAt((methodArray + BaseHeaderSize) + (index << (shiftForWord())));
-					if (((objOop11 & 3) == 0)
-					 && (((longAt(objOop11)) & 0x3FFFFF) == 8)) {
-						objOop11 = fixFollowedFieldofObjectwithInitialValue(index, methodArray, objOop11);
-					}
-					GIV(newMethod) = objOop11;
-					found = 1;
-					goto l1;
-				}
-				index += 1;
-			}
-			found = 0;
-			goto l1;
-		}
-
-		/* It is assumed that there are some nils in this dictionary, and search will
-		   stop when one is encountered. However, if there are no nils, then wrapAround
-		   will be detected the second time the loop gets to the end of the table. */
-
-		index = SelectorStart + (mask & (((GIV(messageSelector) & 3) != 0
-	? ((GIV(messageSelector) & 1)
-			? (GIV(messageSelector) >> 1)
-			: ((usqInt) (((usqInt)GIV(messageSelector)))) >> 2)
-	: (/* begin hashBitsOf: */
-		(objOop4 = GIV(messageSelector)),
-		(hash = (long32At(objOop4 + 4)) & 0x3FFFFF),
-		(hash == 0
-				? ((hash = (newObjectHash()) & 0x3FFFFF),
-					/* begin setHashBitsOf:to: */
-					flag("endianness"),
-					assert(((hash >= 0) && (hash <= (identityHashHalfWordMask())))),
-					long32Atput(objOop4 + 4, ((((long32At(objOop4 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + hash))
-				: 0),
-		hash))));
-		wrapAround = 0;
-		while (1) {
-			nextSelector = longAt((dictionary + BaseHeaderSize) + (index << (shiftForWord())));
-			if (nextSelector == GIV(nilObj)) {
-				found = 0;
-				goto l1;
-			}
-			if (((nextSelector & 3) == 0)
-			 && (((longAt(nextSelector)) & 0x3FFFFF) == 8)) {
-				nextSelector = fixFollowedFieldofObjectwithInitialValue(index + SelectorStart, dictionary, nextSelector);
-			}
-			if (nextSelector == GIV(messageSelector)) {
-				/* begin followObjField:ofObject: */
-				objOop2 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
-				assert(isNonImmediate(objOop2));
-				if (((longAt(objOop2)) & (0x3FFFFF - 8)) == 0) {
-					objOop2 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop2);
-				}
-				methodArray = objOop2;
-				/* begin followField:ofObject: */
-				objOop3 = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << (shiftForWord())));
-				if (((objOop3 & 3) == 0)
-				 && (((longAt(objOop3)) & 0x3FFFFF) == 8)) {
-					objOop3 = fixFollowedFieldofObjectwithInitialValue(index - SelectorStart, methodArray, objOop3);
-				}
-				GIV(newMethod) = objOop3;
-				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 LookupRuleMNU;
-		}
-		/* begin followField:ofObject: */
-		objOop1 = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
-		if (((objOop1 & 3) == 0)
-		 && (((longAt(objOop1)) & 0x3FFFFF) == 8)) {
-			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, currentClass, objOop1);
-		}
-		currentClass = objOop1;
-	}
-	error("Recursive not understood error encountered");
-}
-
-
 /*	This method implements a simple method lookup cache. If an entry for the
 	given selector and classTag is found in the cache, set the values of
 	'newMethod' and
@@ -70813,7 +70702,7 @@
 		? longAt((GIV(classTableFirstPage) + BaseHeaderSize) + (tagBits << (shiftForWord())))
 		: fetchClassOfNonImm(GIV(localAbsentReceiver)));
 
-	/* For use by MNU */
+	/* MNU lookup starts here. */
 
 	GIV(lkupClass) = receiverClass;
 	mixinApplication = findApplicationOfTargetMixinstartingAtBehavior(mixin, receiverClass);
@@ -71110,6 +70999,176 @@
 }
 
 
+/*	A send lookup failed. Replace the arguments on the stack with a Message
+	and lookup
+	#doesNotUndestand: starting at lkupClass. Note that MNU lookup ignores
+	access modifiers.
+	This makes it different from an ordinary send of #doesNotUnderstand:,
+	which must only
+	find public methods.
+	IN: lkupClass
+	IN: messageSelector
+	IN: argumentCount
+	OUT: newMethod
+	OUT: primitiveIndex
+	RESULT: LookupRuleMNU */
+
+	/* StackInterpreter>>#lookupMNU */
+static sqInt
+lookupMNU(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt currentClass;
+    sqInt dictionary;
+    sqInt found;
+    sqInt hash;
+    sqInt index;
+    usqInt length;
+    usqInt mask;
+    sqInt methodArray;
+    sqInt nextSelector;
+    usqInt numSlots;
+    sqInt objOop;
+    sqInt objOop1;
+    sqInt objOop11;
+    sqInt objOop2;
+    sqInt objOop3;
+    sqInt objOop4;
+    sqInt objOop5;
+    sqInt wrapAround;
+
+	createActualMessageTo(GIV(lkupClass));
+	GIV(messageSelector) = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorDoesNotUnderstand << (shiftForWord())));
+	currentClass = GIV(lkupClass);
+	while (currentClass != GIV(nilObj)) {
+		/* begin followObjField:ofObject: */
+		objOop = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
+		assert(isNonImmediate(objOop));
+		if (((longAt(objOop)) & (0x3FFFFF - 8)) == 0) {
+			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, currentClass, objOop);
+		}
+		dictionary = objOop;
+		/* begin lookupMethodInDictionary: */
+		/* begin numSlotsOf: */
+		flag("endianness");
+		assert((classIndexOf(dictionary)) > (isForwardedObjectClassIndexPun()));
+		numSlots = byteAt(dictionary + 7);
+		length = (numSlots == 0xFF
+			? longAt(dictionary - BaseHeaderSize)
+			: numSlots);
+
+		/* Use linear search on small dictionaries; its cheaper.
+		   Also the limit can be set to force linear search of all dictionaries, which supports the
+		   booting of images that need rehashing (e.g. because a tracer has generated an image
+		   with different hashes but hasn't rehashed it yet.) */
+
+		mask = (length - SelectorStart) - 1;
+		if (mask <= GIV(methodDictLinearSearchLimit)) {
+			index = 0;
+			while (index <= mask) {
+				nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << (shiftForWord())));
+				if (((nextSelector & 3) == 0)
+				 && (((longAt(nextSelector)) & 0x3FFFFF) == 8)) {
+					nextSelector = fixFollowedFieldofObjectwithInitialValue(index + SelectorStart, dictionary, nextSelector);
+				}
+				if (nextSelector == GIV(messageSelector)) {
+					/* begin followObjField:ofObject: */
+					objOop5 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
+					assert(isNonImmediate(objOop5));
+					if (((longAt(objOop5)) & (0x3FFFFF - 8)) == 0) {
+						objOop5 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop5);
+					}
+					methodArray = objOop5;
+					/* begin followField:ofObject: */
+					objOop11 = longAt((methodArray + BaseHeaderSize) + (index << (shiftForWord())));
+					if (((objOop11 & 3) == 0)
+					 && (((longAt(objOop11)) & 0x3FFFFF) == 8)) {
+						objOop11 = fixFollowedFieldofObjectwithInitialValue(index, methodArray, objOop11);
+					}
+					GIV(newMethod) = objOop11;
+					found = 1;
+					goto l1;
+				}
+				index += 1;
+			}
+			found = 0;
+			goto l1;
+		}
+
+		/* It is assumed that there are some nils in this dictionary, and search will
+		   stop when one is encountered. However, if there are no nils, then wrapAround
+		   will be detected the second time the loop gets to the end of the table. */
+
+		index = SelectorStart + (mask & (((GIV(messageSelector) & 3) != 0
+	? ((GIV(messageSelector) & 1)
+			? (GIV(messageSelector) >> 1)
+			: ((usqInt) (((usqInt)GIV(messageSelector)))) >> 2)
+	: (/* begin hashBitsOf: */
+		(objOop4 = GIV(messageSelector)),
+		(hash = (long32At(objOop4 + 4)) & 0x3FFFFF),
+		(hash == 0
+				? ((hash = (newObjectHash()) & 0x3FFFFF),
+					/* begin setHashBitsOf:to: */
+					flag("endianness"),
+					assert(((hash >= 0) && (hash <= (identityHashHalfWordMask())))),
+					long32Atput(objOop4 + 4, ((((long32At(objOop4 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + hash))
+				: 0),
+		hash))));
+		wrapAround = 0;
+		while (1) {
+			nextSelector = longAt((dictionary + BaseHeaderSize) + (index << (shiftForWord())));
+			if (nextSelector == GIV(nilObj)) {
+				found = 0;
+				goto l1;
+			}
+			if (((nextSelector & 3) == 0)
+			 && (((longAt(nextSelector)) & 0x3FFFFF) == 8)) {
+				nextSelector = fixFollowedFieldofObjectwithInitialValue(index + SelectorStart, dictionary, nextSelector);
+			}
+			if (nextSelector == GIV(messageSelector)) {
+				/* begin followObjField:ofObject: */
+				objOop2 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
+				assert(isNonImmediate(objOop2));
+				if (((longAt(objOop2)) & (0x3FFFFF - 8)) == 0) {
+					objOop2 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop2);
+				}
+				methodArray = objOop2;
+				/* begin followField:ofObject: */
+				objOop3 = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << (shiftForWord())));
+				if (((objOop3 & 3) == 0)
+				 && (((longAt(objOop3)) & 0x3FFFFF) == 8)) {
+					objOop3 = fixFollowedFieldofObjectwithInitialValue(index - SelectorStart, methodArray, objOop3);
+				}
+				GIV(newMethod) = objOop3;
+				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 LookupRuleMNU;
+		}
+		/* begin followField:ofObject: */
+		objOop1 = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
+		if (((objOop1 & 3) == 0)
+		 && (((longAt(objOop1)) & 0x3FFFFF) == 8)) {
+			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, currentClass, objOop1);
+		}
+		currentClass = objOop1;
+	}
+	error("Recursive not understood error encountered");
+}
+
+
 /*	Lookup messageSelector in class. Answer 0 on success. Answer the splObj:
 	index for the error selector to use on failure rather than performing MNU
 	processing etc. */
@@ -71488,11 +71547,11 @@
 	IN: argumentCount
 	OUT: newMethod
 	OUT: primitiveIndex
-	RESULT: LookupOrdinary or LookupDNU
+	RESULT: LookupRuleOrdinary or LookupRuleMNU
  */
 
 	/* StackInterpreter>>#lookupOrdinarySend */
-static void
+static sqInt
 lookupOrdinarySend(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt currentClass;
@@ -71633,11 +71692,10 @@
 	l1:	/* end lookupMethodInDictionary: */;
 		if (found) {
 			if ((accessModifierOfMethod(GIV(newMethod))) == AccessModifierPublic) {
-				return;
+				return LookupRuleOrdinary;
 			}
 			if ((accessModifierOfMethod(GIV(newMethod))) == AccessModifierProtected) {
-				lookupDnuPresent();
-				return;
+				return lookupMNU();
 			}
 		}
 		/* begin followField:ofObject: */
@@ -71648,8 +71706,7 @@
 		}
 		currentClass = objOop1;
 	}
-	lookupDnuPresent();
-	return;
+	return lookupMNU();
 }
 
 
@@ -71664,49 +71721,30 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt currentClass;
     sqInt dictionary;
-    sqInt dictionary1;
     sqInt found;
-    sqInt found1;
     sqInt hash;
-    sqInt hash1;
     sqInt index;
-    sqInt index1;
     usqInt length;
-    usqInt length1;
-    sqInt lookupClass;
     usqInt mask;
-    usqInt mask1;
     sqInt methodArray;
-    sqInt methodArray1;
     sqInt nextSelector;
-    sqInt nextSelector1;
     usqInt numSlots;
-    usqInt numSlots1;
     sqInt objOop;
     sqInt objOop1;
     sqInt objOop11;
-    sqInt objOop12;
     sqInt objOop2;
-    sqInt objOop21;
-    sqInt objOop22;
     sqInt objOop3;
-    sqInt objOop31;
-    sqInt objOop32;
     sqInt objOop4;
-    sqInt objOop41;
     sqInt objOop5;
-    sqInt objOop6;
-    sqInt tagBits;
     sqInt wrapAround;
-    sqInt wrapAround1;
 
-	lookupClass = mixinApplication;
-	while (!(lookupClass == GIV(nilObj))) {
+	currentClass = mixinApplication;
+	while (!(currentClass == GIV(nilObj))) {
 		/* begin followObjField:ofObject: */
-		objOop = longAt((lookupClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
+		objOop = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
 		assert(isNonImmediate(objOop));
 		if (((longAt(objOop)) & (0x3FFFFF - 8)) == 0) {
-			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, lookupClass, objOop);
+			objOop = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, currentClass, objOop);
 		}
 		dictionary = objOop;
 		/* begin lookupMethodInDictionary: */
@@ -71788,19 +71826,19 @@
 			}
 			if (nextSelector == GIV(messageSelector)) {
 				/* begin followObjField:ofObject: */
-				objOop21 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
-				assert(isNonImmediate(objOop21));
-				if (((longAt(objOop21)) & (0x3FFFFF - 8)) == 0) {
-					objOop21 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop21);
+				objOop2 = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
+				assert(isNonImmediate(objOop2));
+				if (((longAt(objOop2)) & (0x3FFFFF - 8)) == 0) {
+					objOop2 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary, objOop2);
 				}
-				methodArray = objOop21;
+				methodArray = objOop2;
 				/* begin followField:ofObject: */
-				objOop31 = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << (shiftForWord())));
-				if (((objOop31 & 3) == 0)
-				 && (((longAt(objOop31)) & 0x3FFFFF) == 8)) {
-					objOop31 = fixFollowedFieldofObjectwithInitialValue(index - SelectorStart, methodArray, objOop31);
+				objOop3 = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << (shiftForWord())));
+				if (((objOop3 & 3) == 0)
+				 && (((longAt(objOop3)) & 0x3FFFFF) == 8)) {
+					objOop3 = fixFollowedFieldofObjectwithInitialValue(index - SelectorStart, methodArray, objOop3);
 				}
-				GIV(newMethod) = objOop31;
+				GIV(newMethod) = objOop3;
 				found = 1;
 				goto l1;
 			}
@@ -71818,151 +71856,17 @@
 	l1:	/* end lookupMethodInDictionary: */;
 		if (found
 		 && (!((accessModifierOfMethod(GIV(newMethod))) == AccessModifierPrivate))) {
-			return 0;
+			return rule;
 		}
 		/* begin followField:ofObject: */
-		objOop1 = longAt((lookupClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
+		objOop1 = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
 		if (((objOop1 & 3) == 0)
 		 && (((longAt(objOop1)) & 0x3FFFFF) == 8)) {
-			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, lookupClass, objOop1);
+			objOop1 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, currentClass, objOop1);
 		}
-		lookupClass = objOop1;
+		currentClass = objOop1;
 	}
-	/* begin lookupDnuAbsent */
-	createActualMessageTo(GIV(lkupClass));
-	GIV(lkupClass) = (((tagBits = GIV(localAbsentReceiver) & 3)) != 0
-		? longAt((GIV(classTableFirstPage) + BaseHeaderSize) + (tagBits << (shiftForWord())))
-		: fetchClassOfNonImm(GIV(localAbsentReceiver)));
-	GIV(messageSelector) = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (SelectorDoesNotUnderstand << (shiftForWord())));
-	currentClass = GIV(lkupClass);
-	while (currentClass != GIV(nilObj)) {
-		/* begin followObjField:ofObject: */
-		objOop2 = longAt((currentClass + BaseHeaderSize) + (MethodDictionaryIndex << (shiftForWord())));
-		assert(isNonImmediate(objOop2));
-		if (((longAt(objOop2)) & (0x3FFFFF - 8)) == 0) {
-			objOop2 = fixFollowedFieldofObjectwithInitialValue(MethodDictionaryIndex, currentClass, objOop2);
-		}
-		dictionary1 = objOop2;
-		/* begin lookupMethodInDictionary: */
-		/* begin numSlotsOf: */
-		flag("endianness");
-		assert((classIndexOf(dictionary1)) > (isForwardedObjectClassIndexPun()));
-		numSlots1 = byteAt(dictionary1 + 7);
-		length1 = (numSlots1 == 0xFF
-			? longAt(dictionary1 - BaseHeaderSize)
-			: numSlots1);
-
-		/* Use linear search on small dictionaries; its cheaper.
-		   Also the limit can be set to force linear search of all dictionaries, which supports the
-		   booting of images that need rehashing (e.g. because a tracer has generated an image
-		   with different hashes but hasn't rehashed it yet.) */
-
-		mask1 = (length1 - SelectorStart) - 1;
-		if (mask1 <= GIV(methodDictLinearSearchLimit)) {
-			index1 = 0;
-			while (index1 <= mask1) {
-				nextSelector1 = longAt((dictionary1 + BaseHeaderSize) + ((index1 + SelectorStart) << (shiftForWord())));
-				if (((nextSelector1 & 3) == 0)
-				 && (((longAt(nextSelector1)) & 0x3FFFFF) == 8)) {
-					nextSelector1 = fixFollowedFieldofObjectwithInitialValue(index1 + SelectorStart, dictionary1, nextSelector1);
-				}
-				if (nextSelector1 == GIV(messageSelector)) {
-					/* begin followObjField:ofObject: */
-					objOop6 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
-					assert(isNonImmediate(objOop6));
-					if (((longAt(objOop6)) & (0x3FFFFF - 8)) == 0) {
-						objOop6 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary1, objOop6);
-					}
-					methodArray1 = objOop6;
-					/* begin followField:ofObject: */
-					objOop12 = longAt((methodArray1 + BaseHeaderSize) + (index1 << (shiftForWord())));
-					if (((objOop12 & 3) == 0)
-					 && (((longAt(objOop12)) & 0x3FFFFF) == 8)) {
-						objOop12 = fixFollowedFieldofObjectwithInitialValue(index1, methodArray1, objOop12);
-					}
-					GIV(newMethod) = objOop12;
-					found1 = 1;
-					goto l2;
-				}
-				index1 += 1;
-			}
-			found1 = 0;
-			goto l2;
-		}
-
-		/* It is assumed that there are some nils in this dictionary, and search will
-		   stop when one is encountered. However, if there are no nils, then wrapAround
-		   will be detected the second time the loop gets to the end of the table. */
-
-		index1 = SelectorStart + (mask1 & (((GIV(messageSelector) & 3) != 0
-	? ((GIV(messageSelector) & 1)
-			? (GIV(messageSelector) >> 1)
-			: ((usqInt) (((usqInt)GIV(messageSelector)))) >> 2)
-	: (/* begin hashBitsOf: */
-		(objOop41 = GIV(messageSelector)),
-		(hash1 = (long32At(objOop41 + 4)) & 0x3FFFFF),
-		(hash1 == 0
-				? ((hash1 = (newObjectHash()) & 0x3FFFFF),
-					/* begin setHashBitsOf:to: */
-					flag("endianness"),
-					assert(((hash1 >= 0) && (hash1 <= (identityHashHalfWordMask())))),
-					long32Atput(objOop41 + 4, ((((long32At(objOop41 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + hash1))
-				: 0),
-		hash1))));
-		wrapAround1 = 0;
-		while (1) {
-			nextSelector1 = longAt((dictionary1 + BaseHeaderSize) + (index1 << (shiftForWord())));
-			if (nextSelector1 == GIV(nilObj)) {
-				found1 = 0;
-				goto l2;
-			}
-			if (((nextSelector1 & 3) == 0)
-			 && (((longAt(nextSelector1)) & 0x3FFFFF) == 8)) {
-				nextSelector1 = fixFollowedFieldofObjectwithInitialValue(index1 + SelectorStart, dictionary1, nextSelector1);
-			}
-			if (nextSelector1 == GIV(messageSelector)) {
-				/* begin followObjField:ofObject: */
-				objOop22 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << (shiftForWord())));
-				assert(isNonImmediate(objOop22));
-				if (((longAt(objOop22)) & (0x3FFFFF - 8)) == 0) {
-					objOop22 = fixFollowedFieldofObjectwithInitialValue(MethodArrayIndex, dictionary1, objOop22);
-				}
-				methodArray1 = objOop22;
-				/* begin followField:ofObject: */
-				objOop32 = longAt((methodArray1 + BaseHeaderSize) + ((index1 - SelectorStart) << (shiftForWord())));
-				if (((objOop32 & 3) == 0)
-				 && (((longAt(objOop32)) & 0x3FFFFF) == 8)) {
-					objOop32 = fixFollowedFieldofObjectwithInitialValue(index1 - SelectorStart, methodArray1, objOop32);
-				}
-				GIV(newMethod) = objOop32;
-				found1 = 1;
-				goto l2;
-			}
-			index1 += 1;
-			if (index1 == length1) {
-				if (wrapAround1) {
-					found1 = 0;
-					goto l2;
-				}
-				wrapAround1 = 1;
-				index1 = SelectorStart;
-			}
-		}
-		found1 = 0;
-	l2:	/* end lookupMethodInDictionary: */;
-		if (found1) {
-			return LookupRuleMNU;
-		}
-		/* begin followField:ofObject: */
-		objOop3 = longAt((currentClass + BaseHeaderSize) + (SuperclassIndex << (shiftForWord())));
-		if (((objOop3 & 3) == 0)
-		 && (((longAt(objOop3)) & 0x3FFFFF) == 8)) {
-			objOop3 = fixFollowedFieldofObjectwithInitialValue(SuperclassIndex, currentClass, objOop3);
-		}
-		currentClass = objOop3;
-	}
-	error("Recursive not understood error encountered");
-	return null;
+	return lookupMNU();
 }
 
 
@@ -78862,17 +78766,15 @@
 	putLongtoFile(GIV(specialObjectsOop), f);
 	putLongtoFile(newObjectHash(), f);
 	putLongtoFile(ioScreenSize(), f);
-	putLongtoFile((((((GIV(fullScreenFlag) + ((VMBIGENDIAN
+	putLongtoFile(((((GIV(fullScreenFlag) + ((VMBIGENDIAN
 	? 0
-	: 2))) + ((GIV(processHasThreadId)
-	? 4
-	: 0))) + ((GIV(flagInterpretedMethods)
+	: 2))) + ((GIV(flagInterpretedMethods)
 	? 8
 	: 0))) + ((GIV(preemptionYields)
 	? 0
-	: 16))) + ((GIV(noThreadingOfGUIThread)
-	? 32
-	: 0))) + (((GIV(imageHeaderFlags) | 0x3F) - 0x3F)), f);
+	: 16))) + ((GIV(newFinalization)
+	? 0
+	: 64))) + (((GIV(imageHeaderFlags) | 91) - 91)), f);
 	putWord32toFile(extraVMMemory, f);
 	putShorttoFile(desiredNumStackPages, f);
 	putShorttoFile((desiredCogCodeSize + 0x3FF) / 1024, f);
@@ -81538,35 +81440,6 @@
 }
 
 
-/*	Turn the receiver into an ephemeron.
-	TEMPORARY. For testing ephemeron handling in the VM only.
-	Ephemerons should be instantiated from a suitable class. */
-
-	/* StackInterpreterPrimitives>>#primitiveMakeEphemeron */
-EXPORT(sqInt)
-primitiveMakeEphemeron(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt reasonCode;
-
-	if (!((((longAt(GIV(stackPointer))) & 3) == 0)
-		 && ((((((usqInt) (longAt(longAt(GIV(stackPointer))))) >> 24) & 0x1F) <= 1)
-		 || (((((usqInt) (longAt(longAt(GIV(stackPointer))))) >> 24) & 0x1F) == 5)))) {
-		/* begin primitiveFailFor: */
-		reasonCode = (GIV(argumentCount) == 0
-			? PrimErrBadReceiver
-			: PrimErrBadArgument);
-		return (GIV(primFailCode) = reasonCode);
-	}
-	/* begin setFormatOf:to: */
-	assert(((5 >= 0) && (5 <= (formatMask()))));
-	flag("endianness");
-	longAtput(longAt(GIV(stackPointer)), ((longAt(longAt(GIV(stackPointer)))) & ((unsigned int)~(0x1F << 24))) + (5 << 24));
-	/* begin pop: */
-	GIV(stackPointer) += GIV(argumentCount) * BytesPerWord;
-	null;
-}
-
-
 /*	This primitive is assumed to be fast (see e.g.
 	MethodDictionary>>includesKey:) so make it so.
 	N.B. Works forrectly for cogged methods too. */
@@ -82788,15 +82661,13 @@
 		assert(!(isForwarded(result)));
 		longAtput((result + BaseHeaderSize) + (46 << (shiftForWord())), valuePointer15);
 		/* begin storePointerUnchecked:ofObject:withValue: */
-		valuePointer16 = (((((((GIV(processHasThreadId)
-	? 1
-	: 0)) + ((GIV(flagInterpretedMethods)
+		valuePointer16 = (((((((GIV(flagInterpretedMethods)
 	? 2
-	: 0))) + ((GIV(preemptionYields)
+	: 0)) + ((GIV(preemptionYields)
 	? 0
-	: 4))) + ((GIV(noThreadingOfGUIThread)
-	? 8
-	: 0))) << 1) | 1);
+	: 4))) + ((GIV(newFinalization)
+	? 16
+	: 0))) + ((((((usqInt) GIV(imageHeaderFlags)) >> 2) | ((2 + 4) + 16)) - ((2 + 4) + 16)))) << 1) | 1);
 		assert(!(isForwarded(result)));
 		longAtput((result + BaseHeaderSize) + (47 << (shiftForWord())), valuePointer16);
 		/* begin storePointerUnchecked:ofObject:withValue: */
@@ -83130,15 +83001,13 @@
 			result = getDesiredCogCodeSize();
 		}
 		if (arg == 48) {
-			result = (((((((GIV(processHasThreadId)
-	? 1
-	: 0)) + ((GIV(flagInterpretedMethods)
+			result = (((((((GIV(flagInterpretedMethods)
 	? 2
-	: 0))) + ((GIV(preemptionYields)
+	: 0)) + ((GIV(preemptionYields)
 	? 0
-	: 4))) + ((GIV(noThreadingOfGUIThread)
-	? 8
-	: 0))) << 1) | 1);
+	: 4))) + ((GIV(newFinalization)
+	? 16
+	: 0))) + ((((((usqInt) GIV(imageHeaderFlags)) >> 2) | ((2 + 4) + 16)) - ((2 + 4) + 16)))) << 1) | 1);
 		}
 		if (arg == 49) {
 			result = (((ioGetMaxExtSemTableSize()) << 1) | 1);
@@ -83332,26 +83201,23 @@
 	}
 	if (index == 48) {
 		if (arg >= 0) {
-			result = ((((((((((GIV(processHasThreadId)
-	? 1
-	: 0)) + ((GIV(flagInterpretedMethods)
+			result = ((((((((((GIV(flagInterpretedMethods)
 	? 2
-	: 0))) + ((GIV(preemptionYields)
+	: 0)) + ((GIV(preemptionYields)
 	? 0
-	: 4))) + ((GIV(noThreadingOfGUIThread)
-	? 8
-	: 0))) << 1) | 1)) << 1) | 1);
+	: 4))) + ((GIV(newFinalization)
+	? 16
+	: 0))) + ((((((usqInt) GIV(imageHeaderFlags)) >> 2) | ((2 + 4) + 16)) - ((2 + 4) + 16)))) << 1) | 1)) << 1) | 1);
 			/* begin initPrimCall */
 			GIV(primFailCode) = 0;
 			/* begin setCogVMFlags: */
-			if ((((usqInt)arg)) > 15) {
+			if ((((usqInt)arg)) > 0x1F) {
 				GIV(primFailCode) = PrimErrUnsupported;
 				goto l1;
 			}
-			GIV(processHasThreadId) = (arg & 1) != 0;
 			GIV(flagInterpretedMethods) = (arg & 2) != 0;
 			GIV(preemptionYields) = (arg & 4) == 0;

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list