[Vm-dev] [commit][3202] CogVM source as per VMMaker.oscog-eem.1004

commits at squeakvm.org commits at squeakvm.org
Wed Dec 31 22:38:15 UTC 2014


Revision: 3202
Author:   eliot
Date:     2014-12-31 14:38:14 -0800 (Wed, 31 Dec 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.1004

Send cannotReturn for sideways return attemps when there's an unwind-protect.
Old code would erroneously answer unwind-protect even if home could'nt be found.

e.g. This should raise cannot return:

	| b |
	b := [ ^ 42 ].
	[ [b value] ensure: [1] ] fork.
	Processor yield

just as this does:

	| b |
	b := [ ^ 42 ].
	[ b value ] fork.
	Processor yield

Speed up non-local return processing by using the fact that 98% of the time
returns are within the same page.  The search for the home context following
finding an unwind is unnecessary iff the home is married and on the same page.

Refactor commonReturn to eiminate CoInterpreter's version, moving the
divergence into maybeReturnToMachineCodeFrame.

Ensure search for home through the block's closure uses followField:ofObject:.

(related) Revisit the Sista bug fix for followed contexts during scavenging in
VMMaker.oscog-eem.913 of 24 October 2014.  Split isWidowedContext: into a more
careful version, isWidowedContextDuringGC: for use only during scavenging.

Sista: Added code for inline primitive comparison.

Modified Paths:
--------------
    branches/Cog/nscogsrc/vm/cogit.c
    branches/Cog/nscogsrc/vm/cogit.h
    branches/Cog/nscogsrc/vm/cointerp.c
    branches/Cog/nscogsrc/vm/cointerp.h
    branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/cogit.c
    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/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/sistasrc/vm/cogit.c
    branches/Cog/sistasrc/vm/cogit.h
    branches/Cog/sistasrc/vm/cointerp.c
    branches/Cog/sistasrc/vm/cointerp.h
    branches/Cog/sistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/cogit.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.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/vm/cogit.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/nscogsrc/vm/cogit.c
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.c	2014-12-31 22:28:20 UTC (rev 3201)
+++ branches/Cog/nscogsrc/vm/cogit.c	2014-12-31 22:38:14 UTC (rev 3202)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CCodeGenerator VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	StackToRegisterMappingCogit VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4 " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188 " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 

Modified: branches/Cog/nscogsrc/vm/cogit.h
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.h	2014-12-31 22:28:20 UTC (rev 3201)
+++ branches/Cog/nscogsrc/vm/cogit.h	2014-12-31 22:38:14 UTC (rev 3202)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CCodeGenerator VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
  */
 
 

Modified: branches/Cog/nscogsrc/vm/cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.c	2014-12-31 22:28:20 UTC (rev 3201)
+++ branches/Cog/nscogsrc/vm/cointerp.c	2014-12-31 22:38:14 UTC (rev 3202)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
    from
-	CoInterpreter VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CoInterpreter VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -1081,9 +1081,9 @@
 static char * findFrameAboveinPage(char *theFP, StackPage *thePage) NoDbgRegParms;
 static sqInt findHomeForContext(sqInt aContext) NoDbgRegParms;
 static sqInt findMethodWithPrimitiveFromContextUpToContext(sqInt primitive, sqInt senderContext, sqInt homeContext) NoDbgRegParms;
-static sqInt findMethodWithPrimitiveFromFPUpToContext(sqInt primitive, char *startFP, sqInt homeContext) NoDbgRegParms;
 sqInt findSelectorOfMethod(sqInt methArg);
 static char * findSPOfon(char *theFP, StackPage *thePage) NoDbgRegParms;
+static sqInt findUnwindThroughContext(sqInt homeContext) NoDbgRegParms;
 double floatArg(sqInt index);
 sqInt followLiteralofMethod(sqInt offset, sqInt methodPointer);
 sqInt forceInterruptCheck(void);
@@ -1127,6 +1127,7 @@
 sqInt isReadMediatedContextInstVarIndex(sqInt index);
 static sqInt isSingleContext(sqInt aContext) NoDbgRegParms;
 static sqInt isStillMarriedContext(sqInt aContext) NoDbgRegParms;
+static sqInt isWidowedContextDuringGC(sqInt aOnceMarriedContext) NoDbgRegParms;
 static sqInt isWidowedContext(sqInt aOnceMarriedContext) NoDbgRegParms;
 sqInt isWriteMediatedContextInstVarIndex(sqInt index);
 sqInt isKindOfClass(sqInt oop, sqInt aClass);
@@ -1341,8 +1342,8 @@
 _iss sqInt bytecodeSetSelector;
 _iss usqInt freeStart;
 _iss sqInt argumentCount;
+_iss sqInt nilObj;
 _iss usqInt instructionPointer;
-_iss sqInt nilObj;
 _iss usqInt newMethod;
 _iss sqInt messageSelector;
 _iss usqInt youngStart;
@@ -2100,7 +2101,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1001";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1004";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -4324,7 +4325,6 @@
 				char *callerFP;
 				sqInt closure;
 				sqInt contextToReturnTo;
-				sqInt ctxtOrNilOrZero;
 				sqInt currentCtx;
 				char *frameToReturnTo;
 				sqInt home;
@@ -4343,7 +4343,6 @@
 				char *theFP;
 				char *theFP1;
 				char *theFP2;
-				sqInt theMethod;
 				StackPage *thePage;
 				StackPage *thePage1;
 				StackPage *thePage2;
@@ -4382,23 +4381,12 @@
 				(GIV(stackPage)->headFP = localFP);
 				(GIV(stackPage)->headSP = localSP);
 				assert(pageListIsWellFormed());
-				/* begin internalFindUnwindThroughContext: */
 				/* begin externalizeIPandSP */
 				assert((((usqInt)localIP)) != (ceReturnToInterpreterPC()));
 				GIV(instructionPointer) = oopForPointer(localIP);
 				GIV(stackPointer) = localSP;
 				GIV(framePointer) = localFP;
-				/* begin findUnwindThroughContext: */
-				ctxtOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, GIV(framePointer), home);
-				if (ctxtOrNilOrZero == 0) {
-					theMethod = longAt((home + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
-					if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
-						unwindContextOrNilOrZero = home;
-						goto l296;
-					}
-				}
-				unwindContextOrNilOrZero = ctxtOrNilOrZero;
-			l296:	/* end internalFindUnwindThroughContext: */;
+				unwindContextOrNilOrZero = findUnwindThroughContext(home);
 				if (unwindContextOrNilOrZero == GIV(nilObj)) {
 
 					/* error: can't find home on chain; cannot return */
@@ -4540,10 +4528,11 @@
 					assert((callerContextOrNil2 == (nilObject()))
 					 || (isContext(callerContextOrNil2)));
 					currentCtx = callerContextOrNil2;
-					assert(isContext(currentCtx));
 					freeStackPage(GIV(stackPage));
-					while (!((((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
-					 && ((stackPageFor((theFP = frameOfMarriedContext(currentCtx)))) == newPage))) {
+					while (1) {
+						assert(isContext(currentCtx));
+						if ((((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
+						 && ((stackPageFor((theFP = frameOfMarriedContext(currentCtx)))) == newPage)) break;
 						if (((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1)) {
 							/* begin stackPageFor: */
 							/* begin stackPageAt: */
@@ -4593,6 +4582,9 @@
 					localFP = (GIV(stackPage)->headFP);
 				}
 				if (localFP == frameToReturnTo) {
+
+					/* pop the saved IP, push the return value and continue. */
+
 					localIP = pointerForOop(longAtPointer(localSP));
 				}
 				else {
@@ -4605,6 +4597,7 @@
 					localIP = pointerForOop(longAt(callerFP + FoxCallerSavedIP));
 					localSP = (frameCallerSP(callerFP)) - BytesPerWord;
 				}
+				/* begin maybeReturnToMachineCodeFrame */
 				if ((((usqInt)localIP)) < (startOfMemory())) {
 					if ((((usqInt)localIP)) != (ceReturnToInterpreterPC())) {
 
@@ -4625,11 +4618,11 @@
 						GIV(framePointer) = localFP;
 						
 						ceEnterCogCodePopReceiverReg();
-						goto l294;
+						goto l296;
 					}
 					localIP = pointerForOop(longAt(localFP + FoxIFSavedIP));
 				}
-				longAtPointerput(localSP, localReturnValue);
+			l296:	/* end maybeReturnToMachineCodeFrame */;
 				/* begin setMethod: */
 				assert((((usqInt)(longAt(localFP + FoxMethod)))) >= (startOfMemory()));
 				GIV(method) = longAt(localFP + FoxMethod);
@@ -4641,7 +4634,7 @@
 				/* begin fetchNextBytecode */
 				currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
 
-				/* return self */
+				longAtPointerput(localSP, localReturnValue);
 			}
 		l294:	/* end case */;
 			break;
@@ -4844,7 +4837,6 @@
 							GIV(framePointer) = localFP;
 							
 							ceEnterCogCodePopReceiverReg();
-							null;
 							goto l300;
 						}
 						localIP = pointerForOop(longAt(localFP + FoxIFSavedIP));
@@ -4862,7 +4854,7 @@
 					/* begin fetchNextBytecode */
 					currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
 
-					null;
+					/* return self */
 				l300:	/* end baseFrameReturn */;
 					goto l299;
 				}
@@ -14486,7 +14478,6 @@
     char *callerFP;
     sqInt closure;
     sqInt contextToReturnTo;
-    sqInt ctxtOrNilOrZero;
     sqInt currentCtx;
     char *frameToReturnTo;
     sqInt home;
@@ -14517,7 +14508,6 @@
     char *theFP3;
     char *theFP4;
     char *theFP5;
-    sqInt theMethod;
     StackPage *thePage;
     StackPage *thePage1;
     StackPage *thePage2;
@@ -14558,17 +14548,7 @@
 	(GIV(stackPage)->headFP = GIV(framePointer));
 	(GIV(stackPage)->headSP = GIV(stackPointer));
 	assert(pageListIsWellFormed());
-	/* begin findUnwindThroughContext: */
-	ctxtOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, GIV(framePointer), home);
-	if (ctxtOrNilOrZero == 0) {
-		theMethod = longAt((home + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
-		if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
-			unwindContextOrNilOrZero = home;
-			goto l3;
-		}
-	}
-	unwindContextOrNilOrZero = ctxtOrNilOrZero;
-l3:	/* end findUnwindThroughContext: */;
+	unwindContextOrNilOrZero = findUnwindThroughContext(home);
 	if (unwindContextOrNilOrZero == GIV(nilObj)) {
 
 		/* error: can't find home on chain; cannot return */
@@ -14607,10 +14587,10 @@
 			: (byteAt((theFP5 + FoxIFrameFlags) + 2)) != 0)) {
 			assert(isContext(frameContext(theFP5)));
 			ourContext1 = longAt(theFP5 + FoxThisContext);
-			goto l4;
+			goto l3;
 		}
 		ourContext1 = marryFrameSP(theFP5, theSP2);
-	l4:	/* end ensureFrameIsMarried:SP: */;
+	l3:	/* end ensureFrameIsMarried:SP: */;
 		/* begin push: */
 		longAtput((sp4 = GIV(stackPointer) - BytesPerWord), ourContext1);
 		GIV(stackPointer) = sp4;
@@ -45886,8 +45866,18 @@
 static sqInt
 findMethodWithPrimitiveFromContextUpToContext(sqInt primitive, sqInt senderContext, sqInt homeContext)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt callerContextOrNil;
+    sqInt index;
+    sqInt senderContext1;
+    sqInt senderOop;
+    char *startFP;
     sqInt theContext;
+    char *theFP;
+    char *theFPAbove;
     sqInt theMethod;
+    sqInt theMethod1;
+    StackPage *thePage;
+    char *theSP;
 
 	assert((senderContext == (nilObject()))
 	 || (isContext(senderContext)));
@@ -45902,7 +45892,8 @@
 		if (theContext == homeContext) {
 			return 0;
 		}
-		if ((longAt((theContext + BaseHeaderSize) + (ClosureIndex << (shiftForWord())))) == GIV(nilObj)) {
+		if (!((primitive == 0)
+			 || ((longAt((theContext + BaseHeaderSize) + (ClosureIndex << (shiftForWord())))) != GIV(nilObj)))) {
 			theMethod = longAt((theContext + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
 			if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == primitive) {
 				return theContext;
@@ -45913,27 +45904,12 @@
 	if (isWidowedContext(theContext)) {
 		return GIV(nilObj);
 	}
-	return findMethodWithPrimitiveFromFPUpToContext(primitive, frameOfMarriedContext(theContext), homeContext);
-}
-
-
-/*	See findUnwindThroughContext:. Alas this is mutually recursive with
-	findMethodWithPrimitive:FromContext:ThroughContext: instead of iterative.
-	We're doing the simplest thing that could possibly work. Niceties can
-	wait.  */
-
-static sqInt
-findMethodWithPrimitiveFromFPUpToContext(sqInt primitive, char *startFP, sqInt homeContext)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt callerContextOrNil;
-    sqInt index;
-    sqInt senderContext;
-    char *theFP;
-    char *theFPAbove;
-    sqInt theMethod;
-    StackPage *thePage;
-    char *theSP;
-
+	/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+	/* begin frameOfMarriedContext: */
+	senderOop = longAt((theContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
+	/* begin withoutSmallIntegerTags: */
+	assert((senderOop & 1));
+	startFP = pointerForOop(senderOop - 1);
 	theFP = startFP;
 	theFPAbove = startFP;
 	do {
@@ -45943,13 +45919,14 @@
 		 && (homeContext == (longAt(theFP + FoxThisContext)))) {
 			return 0;
 		}
-		if (!(((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+		if (!((primitive == 0)
+			 || (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
 				? ((longAt(theFP + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
-				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0))) {
-			theMethod = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0)))) {
+			theMethod1 = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
 				? ((mframeHomeMethod(theFP))->methodObject)
 				: longAt(theFP + FoxMethod));
-			if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == primitive) {
+			if ((primitiveIndexOfMethodheader(theMethod1, methodHeaderOf(theMethod1))) == primitive) {
 				if (theFP == theFPAbove) {
 					theSP = findSPOfon(theFP, stackPageFor(theFP));
 				}
@@ -45986,12 +45963,12 @@
 	assert(addressCouldBeObj(callerContextOrNil));
 	assert((callerContextOrNil == (nilObject()))
 	 || (isContext(callerContextOrNil)));
-	senderContext = callerContextOrNil;
-	if (!(((senderContext & 1) == 0)
-		 && (((((usqInt) (longAt(senderContext))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
+	senderContext1 = callerContextOrNil;
+	if (!(((senderContext1 & 1) == 0)
+		 && (((((usqInt) (longAt(senderContext1))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
 		return GIV(nilObj);
 	}
-	return findMethodWithPrimitiveFromContextUpToContext(primitive, senderContext, homeContext);
+	return findMethodWithPrimitiveFromContextUpToContext(primitive, senderContext1, homeContext);
 }
 
 sqInt
@@ -46104,6 +46081,118 @@
 }
 
 
+/*	Search for either an unwind-protect (activation of method with primitive
+	198) or homeContext along the sender chain, which ever is found first.
+	Return values:
+	0			home context was found on sender chain with no intervening
+	unwind-protects nilObj		home context could not be found => cannotReturn
+	context		the context of an intervening unwind-protect implies home context
+	was found */
+/*	Almost always (98%) the home is on the same page. */
+
+static sqInt
+findUnwindThroughContext(sqInt homeContext)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt callerContextOrNil;
+    sqInt ctxtOrNilOrZero;
+    sqInt index;
+    sqInt onSamePage;
+    sqInt senderContext;
+    char *theFP;
+    char *theFPAbove;
+    sqInt theMethod;
+    sqInt theMethod1;
+    StackPage *thePage;
+    char *theSP;
+
+
+	/* Since nothing changes we don't need to internalize. */
+
+	onSamePage = ((((longAt((homeContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
+	 && (!(isWidowedContext(homeContext))))
+	 && ((pageIndexFor(GIV(framePointer))) == (pageIndexFor(frameOfMarriedContext(homeContext))));
+	/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+	theFP = GIV(framePointer);
+	theFPAbove = GIV(framePointer);
+	do {
+		if ((((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+			? ((longAt(theFP + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+			: (byteAt((theFP + FoxIFrameFlags) + 2)) != 0))
+		 && (homeContext == (longAt(theFP + FoxThisContext)))) {
+			ctxtOrNilOrZero = 0;
+			goto l1;
+		}
+		if (!((198 == 0)
+			 || (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				? ((longAt(theFP + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
+				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0)))) {
+			theMethod1 = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				? ((mframeHomeMethod(theFP))->methodObject)
+				: longAt(theFP + FoxMethod));
+			if ((primitiveIndexOfMethodheader(theMethod1, methodHeaderOf(theMethod1))) == 198) {
+				if (theFP == theFPAbove) {
+					theSP = findSPOfon(theFP, stackPageFor(theFP));
+				}
+				else {
+					/* begin frameCallerStackPointer: */
+					assert(!(isBaseFrame(theFPAbove)));
+					theSP = (theFPAbove + (frameStackedReceiverOffsetNumArgs(((((usqInt)(longAt(theFPAbove + FoxMethod)))) < (startOfMemory())
+	? ((mframeCogMethod(theFPAbove))->cmNumArgs)
+	: byteAt((theFPAbove + FoxIFrameFlags) + 1))))) + BytesPerWord;
+				}
+				/* begin ensureFrameIsMarried:SP: */
+				if (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+					? ((longAt(theFP + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+					: (byteAt((theFP + FoxIFrameFlags) + 2)) != 0)) {
+					assert(isContext(frameContext(theFP)));
+					ctxtOrNilOrZero = longAt(theFP + FoxThisContext);
+					goto l1;
+				}
+				ctxtOrNilOrZero = marryFrameSP(theFP, theSP);
+				goto l1;
+			}
+		}
+		theFPAbove = theFP;
+		/* begin frameCallerFP: */
+		theFP = pointerForOop(longAt(theFP + FoxSavedFP));
+	} while(theFP != 0);
+	/* begin frameCallerContext: */
+	assert(isBaseFrame(theFPAbove));
+	/* begin stackPageFor: */
+	/* begin stackPageAt: */
+	/* begin pageIndexFor: */
+	assert((((((char *) theFPAbove)) >= (GIV(stackBasePlus1) - 1)) && ((((char *) theFPAbove)) <= (((char *) GIV(pages))))));
+	index = pageIndexForstackBasePlus1bytesPerPage(theFPAbove, GIV(stackBasePlus1), GIV(bytesPerPage));
+	thePage = stackPageAtpages(index, GIV(pages));
+	callerContextOrNil = longAt((thePage->baseAddress));
+	assert(addressCouldBeObj(callerContextOrNil));
+	assert((callerContextOrNil == (nilObject()))
+	 || (isContext(callerContextOrNil)));
+	senderContext = callerContextOrNil;
+	if (!(((senderContext & 1) == 0)
+		 && (((((usqInt) (longAt(senderContext))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
+		ctxtOrNilOrZero = GIV(nilObj);
+		goto l1;
+	}
+	ctxtOrNilOrZero = findMethodWithPrimitiveFromContextUpToContext(198, senderContext, homeContext);
+l1:	/* end findMethodWithPrimitive:FromFP:UpToContext: */;
+	if (onSamePage
+	 || (ctxtOrNilOrZero == 0)) {
+		theMethod = longAt((homeContext + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
+		if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
+			return homeContext;
+		}
+		return 0;
+	}
+	if (!(ctxtOrNilOrZero == GIV(nilObj))) {
+		if ((findMethodWithPrimitiveFromContextUpToContext(0, ctxtOrNilOrZero, homeContext)) == GIV(nilObj)) {
+			return GIV(nilObj);
+		}
+	}
+	return ctxtOrNilOrZero;
+}
+
+
 /*	Like #stackFloatValue: but access method arguments left-to-right */
 
 double
@@ -46861,11 +46950,27 @@
 }
 
 
-/*	See if the argument is married to a live frame or not.
-	If it is not, turn it into a bereaved single context. */
+/*	See if the argument is married to a live frame or not. i.e. see if there
+	is a matching
+	frame whose frameContext field is aOnceMarriedContext, or a forwarder to
+	it. If aOnceMarriedContext is not married to a live frame, turn it into a
+	bereaved single context.
+	This version is for use during scavenging when stack references may be
+	forwarded. Following what appear to be references to forwarded objects on
+	the stack is dangerous;
+	an instruction ponter may be correctly aligned and may point to bytes that
+	just happen
+	to look like a forwarder. So it is only safe to follow fields that we know
+	are frameContext
+	fields; hence the stack page is walked to check that aOnceMarriedContext
+	is pointing to
+	a live frame. This only has to happen during scavenging because after a
+	become: all
+	frameContext fields have been followed and so there is no need to follow
+	forwarders.  */
 
 static sqInt
-isWidowedContext(sqInt aOnceMarriedContext)
+isWidowedContextDuringGC(sqInt aOnceMarriedContext)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt anInteger;
     sqInt index;
@@ -46925,6 +47030,69 @@
 }
 
 
+/*	See if the argument is married to a live frame or not.
+	If it is not, turn it into a bereaved single context. This version is safe
+	for use
+	only when no frameContext fields may be forwarded (as maybe the case
+	when scavenging). Post become: all frameContext fields are followed, and
+	hence nrmally no following of frameCOtext fields is necessary. But during
+	a scavenge one must use isWidowedContextDuringGC:. */
+
+static sqInt
+isWidowedContext(sqInt aOnceMarriedContext)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt anInteger;
+    sqInt index;
+    sqInt senderOop;
+    char *shouldBeFrameCallerField;
+    char *theFrame;
+    StackPage *thePage;
+
+	assert((isContext(aOnceMarriedContext))
+	 && (isMarriedOrWidowedContext(aOnceMarriedContext)));
+	/* begin frameOfMarriedContext: */
+	senderOop = longAt((aOnceMarriedContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
+	/* begin withoutSmallIntegerTags: */
+	assert((senderOop & 1));
+	theFrame = pointerForOop(senderOop - 1);
+	/* begin stackPageFor: */
+	/* begin stackPageAt: */
+	/* begin pageIndexFor: */
+	assert((((((char *) theFrame)) >= (GIV(stackBasePlus1) - 1)) && ((((char *) theFrame)) <= (((char *) GIV(pages))))));
+	index = pageIndexForstackBasePlus1bytesPerPage(theFrame, GIV(stackBasePlus1), GIV(bytesPerPage));
+	thePage = stackPageAtpages(index, GIV(pages));
+	if (!((isFree(thePage))
+		 || (theFrame < ((thePage->headFP))))) {
+
+		/* The frame pointer is within the bounds of a live page.
+		   Now check if it matches a frame. */
+
+		/* begin withoutSmallIntegerTags: */
+		anInteger = longAt((aOnceMarriedContext + BaseHeaderSize) + (InstructionPointerIndex << (shiftForWord())));
+		assert((anInteger & 1));
+		shouldBeFrameCallerField = pointerForOop(anInteger - 1);
+		if (((frameCallerFP(theFrame)) == shouldBeFrameCallerField)
+		 && (((((usqInt)(longAt(theFrame + FoxMethod)))) < (startOfMemory())
+			? ((longAt(theFrame + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+			: (byteAt((theFrame + FoxIFrameFlags) + 2)) != 0))) {
+			assert(!(((isFrameonPage(theFrame, thePage))
+ && (isForwarded(frameContext(theFrame))))));
+			if ((longAt(theFrame + FoxThisContext)) == aOnceMarriedContext) {
+
+				/* It is still married! */
+
+				return 0;
+			}
+		}
+	}
+	/* begin markContextAsDead: */
+	assert(isContext(aOnceMarriedContext));
+	longAtput((aOnceMarriedContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())), GIV(nilObj));
+	longAtput((aOnceMarriedContext + BaseHeaderSize) + (InstructionPointerIndex << (shiftForWord())), GIV(nilObj));
+	return 1;
+}
+
+
 /*	Wrining any inst vars of a context must take account of potentially
 	married contexts
 	and set the state in the frame. Inst vars in subclasses don't need
@@ -51516,7 +51684,7 @@
     StackPage *thePage;
 
 	if ((((longAt((aContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
-	 && (!(isWidowedContext(aContext)))) {
+	 && (!(isWidowedContextDuringGC(aContext)))) {
 		/* begin stackPageFor: */
 		/* begin frameOfMarriedContext: */
 		senderOop = longAt((aContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
@@ -54883,12 +55051,21 @@
 primitiveFindNextUnwindContext(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt calleeContext;
+    sqInt callerContextOrNil;
     sqInt handlerOrNilOrZero;
+    sqInt index;
+    sqInt senderContext;
     sqInt senderOop;
     char *sp;
     sqInt startContext;
+    char *startFP;
     sqInt stopContext;
     char *theFP;
+    char *theFP1;
+    char *theFPAbove;
+    sqInt theMethod;
+    StackPage *thePage;
+    char *theSP;
 
 	stopContext = longAt(GIV(stackPointer));
 	calleeContext = longAt(GIV(stackPointer) + (1 * BytesPerWord));
@@ -54924,7 +55101,73 @@
 			handlerOrNilOrZero = findMethodWithPrimitiveFromContextUpToContext(198, frameCallerContext(theFP), stopContext);
 		}
 		else {
-			handlerOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, frameCallerFP(theFP), stopContext);
+			/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+			/* begin frameCallerFP: */
+			startFP = pointerForOop(longAt(theFP + FoxSavedFP));
+			theFP1 = startFP;
+			theFPAbove = startFP;
+			do {
+				if ((((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+					? ((longAt(theFP1 + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+					: (byteAt((theFP1 + FoxIFrameFlags) + 2)) != 0))
+				 && (stopContext == (longAt(theFP1 + FoxThisContext)))) {
+					handlerOrNilOrZero = 0;
+					goto l1;
+				}
+				if (!((198 == 0)
+					 || (((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+						? ((longAt(theFP1 + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
+						: (byteAt((theFP1 + FoxIFrameFlags) + 3)) != 0)))) {
+					theMethod = ((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+						? ((mframeHomeMethod(theFP1))->methodObject)
+						: longAt(theFP1 + FoxMethod));
+					if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
+						if (theFP1 == theFPAbove) {
+							theSP = findSPOfon(theFP1, stackPageFor(theFP1));
+						}
+						else {
+							/* begin frameCallerStackPointer: */
+							assert(!(isBaseFrame(theFPAbove)));
+							theSP = (theFPAbove + (frameStackedReceiverOffsetNumArgs(((((usqInt)(longAt(theFPAbove + FoxMethod)))) < (startOfMemory())
+	? ((mframeCogMethod(theFPAbove))->cmNumArgs)
+	: byteAt((theFPAbove + FoxIFrameFlags) + 1))))) + BytesPerWord;
+						}
+						/* begin ensureFrameIsMarried:SP: */
+						if (((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+							? ((longAt(theFP1 + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+							: (byteAt((theFP1 + FoxIFrameFlags) + 2)) != 0)) {
+							assert(isContext(frameContext(theFP1)));
+							handlerOrNilOrZero = longAt(theFP1 + FoxThisContext);
+							goto l1;
+						}
+						handlerOrNilOrZero = marryFrameSP(theFP1, theSP);
+						goto l1;
+					}
+				}
+				theFPAbove = theFP1;
+				/* begin frameCallerFP: */
+				theFP1 = pointerForOop(longAt(theFP1 + FoxSavedFP));
+			} while(theFP1 != 0);
+			/* begin frameCallerContext: */
+			assert(isBaseFrame(theFPAbove));
+			/* begin stackPageFor: */
+			/* begin stackPageAt: */
+			/* begin pageIndexFor: */
+			assert((((((char *) theFPAbove)) >= (GIV(stackBasePlus1) - 1)) && ((((char *) theFPAbove)) <= (((char *) GIV(pages))))));
+			index = pageIndexForstackBasePlus1bytesPerPage(theFPAbove, GIV(stackBasePlus1), GIV(bytesPerPage));
+			thePage = stackPageAtpages(index, GIV(pages));
+			callerContextOrNil = longAt((thePage->baseAddress));
+			assert(addressCouldBeObj(callerContextOrNil));
+			assert((callerContextOrNil == (nilObject()))
+			 || (isContext(callerContextOrNil)));
+			senderContext = callerContextOrNil;
+			if (!(((senderContext & 1) == 0)
+				 && (((((usqInt) (longAt(senderContext))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
+				handlerOrNilOrZero = GIV(nilObj);
+				goto l1;
+			}
+			handlerOrNilOrZero = findMethodWithPrimitiveFromContextUpToContext(198, senderContext, stopContext);
+		l1:	/* end findMethodWithPrimitive:FromFP:UpToContext: */;
 		}
 	}
 	else {

Modified: branches/Cog/nscogsrc/vm/cointerp.h
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.h	2014-12-31 22:28:20 UTC (rev 3201)
+++ branches/Cog/nscogsrc/vm/cointerp.h	2014-12-31 22:38:14 UTC (rev 3202)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
  */
 
 

Modified: branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-12-31 22:28:20 UTC (rev 3201)
+++ branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-12-31 22:38:14 UTC (rev 3202)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
    from
-	CoInterpreter VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4
+	CoInterpreter VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1001 uuid: fef56678-07b1-4fca-8300-17d6afc0c6e4 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1004 uuid: 132642b3-ab26-4957-82a4-8aa19b60f188 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -1084,9 +1084,9 @@
 static char * findFrameAboveinPage(char *theFP, StackPage *thePage) NoDbgRegParms;
 static sqInt findHomeForContext(sqInt aContext) NoDbgRegParms;
 static sqInt findMethodWithPrimitiveFromContextUpToContext(sqInt primitive, sqInt senderContext, sqInt homeContext) NoDbgRegParms;
-static sqInt findMethodWithPrimitiveFromFPUpToContext(sqInt primitive, char *startFP, sqInt homeContext) NoDbgRegParms;
 sqInt findSelectorOfMethod(sqInt methArg);
 static char * findSPOfon(char *theFP, StackPage *thePage) NoDbgRegParms;
+static sqInt findUnwindThroughContext(sqInt homeContext) NoDbgRegParms;
 double floatArg(sqInt index);
 sqInt followLiteralofMethod(sqInt offset, sqInt methodPointer);
 sqInt forceInterruptCheck(void);
@@ -1130,6 +1130,7 @@
 sqInt isReadMediatedContextInstVarIndex(sqInt index);
 static sqInt isSingleContext(sqInt aContext) NoDbgRegParms;
 static sqInt isStillMarriedContext(sqInt aContext) NoDbgRegParms;
+static sqInt isWidowedContextDuringGC(sqInt aOnceMarriedContext) NoDbgRegParms;
 static sqInt isWidowedContext(sqInt aOnceMarriedContext) NoDbgRegParms;
 sqInt isWriteMediatedContextInstVarIndex(sqInt index);
 sqInt isKindOfClass(sqInt oop, sqInt aClass);
@@ -1344,8 +1345,8 @@
 _iss sqInt bytecodeSetSelector;
 _iss usqInt freeStart;
 _iss sqInt argumentCount;
+_iss sqInt nilObj;
 _iss usqInt instructionPointer;
-_iss sqInt nilObj;
 _iss usqInt newMethod;
 _iss sqInt messageSelector;
 _iss usqInt youngStart;
@@ -2103,7 +2104,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1001";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1004";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -4333,7 +4334,6 @@
 				char *callerFP;
 				sqInt closure;
 				sqInt contextToReturnTo;
-				sqInt ctxtOrNilOrZero;
 				sqInt currentCtx;
 				char *frameToReturnTo;
 				sqInt home;
@@ -4352,7 +4352,6 @@
 				char *theFP;
 				char *theFP1;
 				char *theFP2;
-				sqInt theMethod;
 				StackPage *thePage;
 				StackPage *thePage1;
 				StackPage *thePage2;
@@ -4391,23 +4390,12 @@
 				(GIV(stackPage)->headFP = localFP);
 				(GIV(stackPage)->headSP = localSP);
 				assert(pageListIsWellFormed());
-				/* begin internalFindUnwindThroughContext: */
 				/* begin externalizeIPandSP */
 				assert((((usqInt)localIP)) != (ceReturnToInterpreterPC()));
 				GIV(instructionPointer) = oopForPointer(localIP);
 				GIV(stackPointer) = localSP;
 				GIV(framePointer) = localFP;
-				/* begin findUnwindThroughContext: */
-				ctxtOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, GIV(framePointer), home);
-				if (ctxtOrNilOrZero == 0) {
-					theMethod = longAt((home + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
-					if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
-						unwindContextOrNilOrZero = home;
-						goto l296;
-					}
-				}
-				unwindContextOrNilOrZero = ctxtOrNilOrZero;
-			l296:	/* end internalFindUnwindThroughContext: */;
+				unwindContextOrNilOrZero = findUnwindThroughContext(home);
 				if (unwindContextOrNilOrZero == GIV(nilObj)) {
 
 					/* error: can't find home on chain; cannot return */
@@ -4549,10 +4537,11 @@
 					assert((callerContextOrNil2 == (nilObject()))
 					 || (isContext(callerContextOrNil2)));
 					currentCtx = callerContextOrNil2;
-					assert(isContext(currentCtx));
 					freeStackPage(GIV(stackPage));
-					while (!((((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
-					 && ((stackPageFor((theFP = frameOfMarriedContext(currentCtx)))) == newPage))) {
+					while (1) {
+						assert(isContext(currentCtx));
+						if ((((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
+						 && ((stackPageFor((theFP = frameOfMarriedContext(currentCtx)))) == newPage)) break;
 						if (((longAt((currentCtx + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1)) {
 							/* begin stackPageFor: */
 							/* begin stackPageAt: */
@@ -4602,6 +4591,9 @@
 					localFP = (GIV(stackPage)->headFP);
 				}
 				if (localFP == frameToReturnTo) {
+
+					/* pop the saved IP, push the return value and continue. */
+
 					localIP = pointerForOop(longAtPointer(localSP));
 				}
 				else {
@@ -4614,6 +4606,7 @@
 					localIP = pointerForOop(longAt(callerFP + FoxCallerSavedIP));
 					localSP = (frameCallerSP(callerFP)) - BytesPerWord;
 				}
+				/* begin maybeReturnToMachineCodeFrame */
 				if ((((usqInt)localIP)) < (startOfMemory())) {
 					if ((((usqInt)localIP)) != (ceReturnToInterpreterPC())) {
 
@@ -4634,11 +4627,11 @@
 						GIV(framePointer) = localFP;
 						
 						ceEnterCogCodePopReceiverReg();
-						goto l294;
+						goto l296;
 					}
 					localIP = pointerForOop(longAt(localFP + FoxIFSavedIP));
 				}
-				longAtPointerput(localSP, localReturnValue);
+			l296:	/* end maybeReturnToMachineCodeFrame */;
 				/* begin setMethod: */
 				assert((((usqInt)(longAt(localFP + FoxMethod)))) >= (startOfMemory()));
 				GIV(method) = longAt(localFP + FoxMethod);
@@ -4650,7 +4643,7 @@
 				/* begin fetchNextBytecode */
 				currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
 
-				/* return self */
+				longAtPointerput(localSP, localReturnValue);
 			}
 		l294:	/* end case */;
 			BREAK;
@@ -4853,7 +4846,6 @@
 							GIV(framePointer) = localFP;
 							
 							ceEnterCogCodePopReceiverReg();
-							null;
 							goto l300;
 						}
 						localIP = pointerForOop(longAt(localFP + FoxIFSavedIP));
@@ -4871,7 +4863,7 @@
 					/* begin fetchNextBytecode */
 					currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
 
-					null;
+					/* return self */
 				l300:	/* end baseFrameReturn */;
 					goto l299;
 				}
@@ -14495,7 +14487,6 @@
     char *callerFP;
     sqInt closure;
     sqInt contextToReturnTo;
-    sqInt ctxtOrNilOrZero;
     sqInt currentCtx;
     char *frameToReturnTo;
     sqInt home;
@@ -14526,7 +14517,6 @@
     char *theFP3;
     char *theFP4;
     char *theFP5;
-    sqInt theMethod;
     StackPage *thePage;
     StackPage *thePage1;
     StackPage *thePage2;
@@ -14567,17 +14557,7 @@
 	(GIV(stackPage)->headFP = GIV(framePointer));
 	(GIV(stackPage)->headSP = GIV(stackPointer));
 	assert(pageListIsWellFormed());
-	/* begin findUnwindThroughContext: */
-	ctxtOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, GIV(framePointer), home);
-	if (ctxtOrNilOrZero == 0) {
-		theMethod = longAt((home + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
-		if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
-			unwindContextOrNilOrZero = home;
-			goto l3;
-		}
-	}
-	unwindContextOrNilOrZero = ctxtOrNilOrZero;
-l3:	/* end findUnwindThroughContext: */;
+	unwindContextOrNilOrZero = findUnwindThroughContext(home);
 	if (unwindContextOrNilOrZero == GIV(nilObj)) {
 
 		/* error: can't find home on chain; cannot return */
@@ -14616,10 +14596,10 @@
 			: (byteAt((theFP5 + FoxIFrameFlags) + 2)) != 0)) {
 			assert(isContext(frameContext(theFP5)));
 			ourContext1 = longAt(theFP5 + FoxThisContext);
-			goto l4;
+			goto l3;
 		}
 		ourContext1 = marryFrameSP(theFP5, theSP2);
-	l4:	/* end ensureFrameIsMarried:SP: */;
+	l3:	/* end ensureFrameIsMarried:SP: */;
 		/* begin push: */
 		longAtput((sp4 = GIV(stackPointer) - BytesPerWord), ourContext1);
 		GIV(stackPointer) = sp4;
@@ -45895,8 +45875,18 @@
 static sqInt
 findMethodWithPrimitiveFromContextUpToContext(sqInt primitive, sqInt senderContext, sqInt homeContext)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt callerContextOrNil;
+    sqInt index;
+    sqInt senderContext1;
+    sqInt senderOop;
+    char *startFP;
     sqInt theContext;
+    char *theFP;
+    char *theFPAbove;
     sqInt theMethod;
+    sqInt theMethod1;
+    StackPage *thePage;
+    char *theSP;
 
 	assert((senderContext == (nilObject()))
 	 || (isContext(senderContext)));
@@ -45911,7 +45901,8 @@
 		if (theContext == homeContext) {
 			return 0;
 		}
-		if ((longAt((theContext + BaseHeaderSize) + (ClosureIndex << (shiftForWord())))) == GIV(nilObj)) {
+		if (!((primitive == 0)
+			 || ((longAt((theContext + BaseHeaderSize) + (ClosureIndex << (shiftForWord())))) != GIV(nilObj)))) {
 			theMethod = longAt((theContext + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
 			if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == primitive) {
 				return theContext;
@@ -45922,27 +45913,12 @@
 	if (isWidowedContext(theContext)) {
 		return GIV(nilObj);
 	}
-	return findMethodWithPrimitiveFromFPUpToContext(primitive, frameOfMarriedContext(theContext), homeContext);
-}
-
-
-/*	See findUnwindThroughContext:. Alas this is mutually recursive with
-	findMethodWithPrimitive:FromContext:ThroughContext: instead of iterative.
-	We're doing the simplest thing that could possibly work. Niceties can
-	wait.  */
-
-static sqInt
-findMethodWithPrimitiveFromFPUpToContext(sqInt primitive, char *startFP, sqInt homeContext)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt callerContextOrNil;
-    sqInt index;
-    sqInt senderContext;
-    char *theFP;
-    char *theFPAbove;
-    sqInt theMethod;
-    StackPage *thePage;
-    char *theSP;
-
+	/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+	/* begin frameOfMarriedContext: */
+	senderOop = longAt((theContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
+	/* begin withoutSmallIntegerTags: */
+	assert((senderOop & 1));
+	startFP = pointerForOop(senderOop - 1);
 	theFP = startFP;
 	theFPAbove = startFP;
 	do {
@@ -45952,13 +45928,14 @@
 		 && (homeContext == (longAt(theFP + FoxThisContext)))) {
 			return 0;
 		}
-		if (!(((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+		if (!((primitive == 0)
+			 || (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
 				? ((longAt(theFP + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
-				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0))) {
-			theMethod = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0)))) {
+			theMethod1 = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
 				? ((mframeHomeMethod(theFP))->methodObject)
 				: longAt(theFP + FoxMethod));
-			if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == primitive) {
+			if ((primitiveIndexOfMethodheader(theMethod1, methodHeaderOf(theMethod1))) == primitive) {
 				if (theFP == theFPAbove) {
 					theSP = findSPOfon(theFP, stackPageFor(theFP));
 				}
@@ -45995,12 +45972,12 @@
 	assert(addressCouldBeObj(callerContextOrNil));
 	assert((callerContextOrNil == (nilObject()))
 	 || (isContext(callerContextOrNil)));
-	senderContext = callerContextOrNil;
-	if (!(((senderContext & 1) == 0)
-		 && (((((usqInt) (longAt(senderContext))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
+	senderContext1 = callerContextOrNil;
+	if (!(((senderContext1 & 1) == 0)
+		 && (((((usqInt) (longAt(senderContext1))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
 		return GIV(nilObj);
 	}
-	return findMethodWithPrimitiveFromContextUpToContext(primitive, senderContext, homeContext);
+	return findMethodWithPrimitiveFromContextUpToContext(primitive, senderContext1, homeContext);
 }
 
 sqInt
@@ -46113,6 +46090,118 @@
 }
 
 
+/*	Search for either an unwind-protect (activation of method with primitive
+	198) or homeContext along the sender chain, which ever is found first.
+	Return values:
+	0			home context was found on sender chain with no intervening
+	unwind-protects nilObj		home context could not be found => cannotReturn
+	context		the context of an intervening unwind-protect implies home context
+	was found */
+/*	Almost always (98%) the home is on the same page. */
+
+static sqInt
+findUnwindThroughContext(sqInt homeContext)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt callerContextOrNil;
+    sqInt ctxtOrNilOrZero;
+    sqInt index;
+    sqInt onSamePage;
+    sqInt senderContext;
+    char *theFP;
+    char *theFPAbove;
+    sqInt theMethod;
+    sqInt theMethod1;
+    StackPage *thePage;
+    char *theSP;
+
+
+	/* Since nothing changes we don't need to internalize. */
+
+	onSamePage = ((((longAt((homeContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
+	 && (!(isWidowedContext(homeContext))))
+	 && ((pageIndexFor(GIV(framePointer))) == (pageIndexFor(frameOfMarriedContext(homeContext))));
+	/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+	theFP = GIV(framePointer);
+	theFPAbove = GIV(framePointer);
+	do {
+		if ((((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+			? ((longAt(theFP + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+			: (byteAt((theFP + FoxIFrameFlags) + 2)) != 0))
+		 && (homeContext == (longAt(theFP + FoxThisContext)))) {
+			ctxtOrNilOrZero = 0;
+			goto l1;
+		}
+		if (!((198 == 0)
+			 || (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				? ((longAt(theFP + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
+				: (byteAt((theFP + FoxIFrameFlags) + 3)) != 0)))) {
+			theMethod1 = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+				? ((mframeHomeMethod(theFP))->methodObject)
+				: longAt(theFP + FoxMethod));
+			if ((primitiveIndexOfMethodheader(theMethod1, methodHeaderOf(theMethod1))) == 198) {
+				if (theFP == theFPAbove) {
+					theSP = findSPOfon(theFP, stackPageFor(theFP));
+				}
+				else {
+					/* begin frameCallerStackPointer: */
+					assert(!(isBaseFrame(theFPAbove)));
+					theSP = (theFPAbove + (frameStackedReceiverOffsetNumArgs(((((usqInt)(longAt(theFPAbove + FoxMethod)))) < (startOfMemory())
+	? ((mframeCogMethod(theFPAbove))->cmNumArgs)
+	: byteAt((theFPAbove + FoxIFrameFlags) + 1))))) + BytesPerWord;
+				}
+				/* begin ensureFrameIsMarried:SP: */
+				if (((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
+					? ((longAt(theFP + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+					: (byteAt((theFP + FoxIFrameFlags) + 2)) != 0)) {
+					assert(isContext(frameContext(theFP)));
+					ctxtOrNilOrZero = longAt(theFP + FoxThisContext);
+					goto l1;
+				}
+				ctxtOrNilOrZero = marryFrameSP(theFP, theSP);
+				goto l1;
+			}
+		}
+		theFPAbove = theFP;
+		/* begin frameCallerFP: */
+		theFP = pointerForOop(longAt(theFP + FoxSavedFP));
+	} while(theFP != 0);
+	/* begin frameCallerContext: */
+	assert(isBaseFrame(theFPAbove));
+	/* begin stackPageFor: */
+	/* begin stackPageAt: */
+	/* begin pageIndexFor: */
+	assert((((((char *) theFPAbove)) >= (GIV(stackBasePlus1) - 1)) && ((((char *) theFPAbove)) <= (((char *) GIV(pages))))));
+	index = pageIndexForstackBasePlus1bytesPerPage(theFPAbove, GIV(stackBasePlus1), GIV(bytesPerPage));
+	thePage = stackPageAtpages(index, GIV(pages));
+	callerContextOrNil = longAt((thePage->baseAddress));
+	assert(addressCouldBeObj(callerContextOrNil));
+	assert((callerContextOrNil == (nilObject()))
+	 || (isContext(callerContextOrNil)));
+	senderContext = callerContextOrNil;
+	if (!(((senderContext & 1) == 0)
+		 && (((((usqInt) (longAt(senderContext))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex))) {
+		ctxtOrNilOrZero = GIV(nilObj);
+		goto l1;
+	}
+	ctxtOrNilOrZero = findMethodWithPrimitiveFromContextUpToContext(198, senderContext, homeContext);
+l1:	/* end findMethodWithPrimitive:FromFP:UpToContext: */;
+	if (onSamePage
+	 || (ctxtOrNilOrZero == 0)) {
+		theMethod = longAt((homeContext + BaseHeaderSize) + (MethodIndex << (shiftForWord())));
+		if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
+			return homeContext;
+		}
+		return 0;
+	}
+	if (!(ctxtOrNilOrZero == GIV(nilObj))) {
+		if ((findMethodWithPrimitiveFromContextUpToContext(0, ctxtOrNilOrZero, homeContext)) == GIV(nilObj)) {
+			return GIV(nilObj);
+		}
+	}
+	return ctxtOrNilOrZero;
+}
+
+
 /*	Like #stackFloatValue: but access method arguments left-to-right */
 
 double
@@ -46870,11 +46959,27 @@
 }
 
 
-/*	See if the argument is married to a live frame or not.
-	If it is not, turn it into a bereaved single context. */
+/*	See if the argument is married to a live frame or not. i.e. see if there
+	is a matching
+	frame whose frameContext field is aOnceMarriedContext, or a forwarder to
+	it. If aOnceMarriedContext is not married to a live frame, turn it into a
+	bereaved single context.
+	This version is for use during scavenging when stack references may be
+	forwarded. Following what appear to be references to forwarded objects on
+	the stack is dangerous;
+	an instruction ponter may be correctly aligned and may point to bytes that
+	just happen
+	to look like a forwarder. So it is only safe to follow fields that we know
+	are frameContext
+	fields; hence the stack page is walked to check that aOnceMarriedContext
+	is pointing to
+	a live frame. This only has to happen during scavenging because after a
+	become: all
+	frameContext fields have been followed and so there is no need to follow
+	forwarders.  */
 
 static sqInt
-isWidowedContext(sqInt aOnceMarriedContext)
+isWidowedContextDuringGC(sqInt aOnceMarriedContext)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt anInteger;
     sqInt index;
@@ -46934,6 +47039,69 @@
 }
 
 
+/*	See if the argument is married to a live frame or not.
+	If it is not, turn it into a bereaved single context. This version is safe
+	for use
+	only when no frameContext fields may be forwarded (as maybe the case
+	when scavenging). Post become: all frameContext fields are followed, and
+	hence nrmally no following of frameCOtext fields is necessary. But during
+	a scavenge one must use isWidowedContextDuringGC:. */
+
+static sqInt
+isWidowedContext(sqInt aOnceMarriedContext)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt anInteger;
+    sqInt index;
+    sqInt senderOop;
+    char *shouldBeFrameCallerField;
+    char *theFrame;
+    StackPage *thePage;
+
+	assert((isContext(aOnceMarriedContext))
+	 && (isMarriedOrWidowedContext(aOnceMarriedContext)));
+	/* begin frameOfMarriedContext: */
+	senderOop = longAt((aOnceMarriedContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
+	/* begin withoutSmallIntegerTags: */
+	assert((senderOop & 1));
+	theFrame = pointerForOop(senderOop - 1);
+	/* begin stackPageFor: */
+	/* begin stackPageAt: */
+	/* begin pageIndexFor: */
+	assert((((((char *) theFrame)) >= (GIV(stackBasePlus1) - 1)) && ((((char *) theFrame)) <= (((char *) GIV(pages))))));
+	index = pageIndexForstackBasePlus1bytesPerPage(theFrame, GIV(stackBasePlus1), GIV(bytesPerPage));
+	thePage = stackPageAtpages(index, GIV(pages));
+	if (!((isFree(thePage))
+		 || (theFrame < ((thePage->headFP))))) {
+
+		/* The frame pointer is within the bounds of a live page.
+		   Now check if it matches a frame. */
+
+		/* begin withoutSmallIntegerTags: */
+		anInteger = longAt((aOnceMarriedContext + BaseHeaderSize) + (InstructionPointerIndex << (shiftForWord())));
+		assert((anInteger & 1));
+		shouldBeFrameCallerField = pointerForOop(anInteger - 1);
+		if (((frameCallerFP(theFrame)) == shouldBeFrameCallerField)
+		 && (((((usqInt)(longAt(theFrame + FoxMethod)))) < (startOfMemory())
+			? ((longAt(theFrame + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+			: (byteAt((theFrame + FoxIFrameFlags) + 2)) != 0))) {
+			assert(!(((isFrameonPage(theFrame, thePage))
+ && (isForwarded(frameContext(theFrame))))));
+			if ((longAt(theFrame + FoxThisContext)) == aOnceMarriedContext) {
+
+				/* It is still married! */
+
+				return 0;
+			}
+		}
+	}
+	/* begin markContextAsDead: */
+	assert(isContext(aOnceMarriedContext));
+	longAtput((aOnceMarriedContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())), GIV(nilObj));
+	longAtput((aOnceMarriedContext + BaseHeaderSize) + (InstructionPointerIndex << (shiftForWord())), GIV(nilObj));
+	return 1;
+}
+
+
 /*	Wrining any inst vars of a context must take account of potentially
 	married contexts
 	and set the state in the frame. Inst vars in subclasses don't need
@@ -51525,7 +51693,7 @@
     StackPage *thePage;
 
 	if ((((longAt((aContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())))) & 1))
-	 && (!(isWidowedContext(aContext)))) {
+	 && (!(isWidowedContextDuringGC(aContext)))) {
 		/* begin stackPageFor: */
 		/* begin frameOfMarriedContext: */
 		senderOop = longAt((aContext + BaseHeaderSize) + (SenderIndex << (shiftForWord())));
@@ -54892,12 +55060,21 @@
 primitiveFindNextUnwindContext(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt calleeContext;
+    sqInt callerContextOrNil;
     sqInt handlerOrNilOrZero;
+    sqInt index;
+    sqInt senderContext;
     sqInt senderOop;
     char *sp;
     sqInt startContext;
+    char *startFP;
     sqInt stopContext;
     char *theFP;
+    char *theFP1;
+    char *theFPAbove;
+    sqInt theMethod;
+    StackPage *thePage;
+    char *theSP;
 
 	stopContext = longAt(GIV(stackPointer));
 	calleeContext = longAt(GIV(stackPointer) + (1 * BytesPerWord));
@@ -54933,7 +55110,73 @@
 			handlerOrNilOrZero = findMethodWithPrimitiveFromContextUpToContext(198, frameCallerContext(theFP), stopContext);
 		}
 		else {
-			handlerOrNilOrZero = findMethodWithPrimitiveFromFPUpToContext(198, frameCallerFP(theFP), stopContext);
+			/* begin findMethodWithPrimitive:FromFP:UpToContext: */
+			/* begin frameCallerFP: */
+			startFP = pointerForOop(longAt(theFP + FoxSavedFP));
+			theFP1 = startFP;
+			theFPAbove = startFP;
+			do {
+				if ((((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+					? ((longAt(theFP1 + FoxMethod)) & MFMethodFlagHasContextFlag) != 0
+					: (byteAt((theFP1 + FoxIFrameFlags) + 2)) != 0))
+				 && (stopContext == (longAt(theFP1 + FoxThisContext)))) {
+					handlerOrNilOrZero = 0;
+					goto l1;
+				}
+				if (!((198 == 0)
+					 || (((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+						? ((longAt(theFP1 + FoxMethod)) & MFMethodFlagIsBlockFlag) != 0
+						: (byteAt((theFP1 + FoxIFrameFlags) + 3)) != 0)))) {
+					theMethod = ((((usqInt)(longAt(theFP1 + FoxMethod)))) < (startOfMemory())
+						? ((mframeHomeMethod(theFP1))->methodObject)
+						: longAt(theFP1 + FoxMethod));
+					if ((primitiveIndexOfMethodheader(theMethod, methodHeaderOf(theMethod))) == 198) {
+						if (theFP1 == theFPAbove) {
+							theSP = findSPOfon(theFP1, stackPageFor(theFP1));
+						}
+						else {
+							/* begin frameCallerStackPointer: */
+							assert(!(isBaseFrame(theFPAbove)));
+							theSP = (theFPAbove + (frameStackedReceiverOffsetNumArgs(((((usqInt)(longAt(theFPAbove + FoxMethod)))) < (startOfMemory())
+	? ((mframeCogMethod(theFPAbove))->cmNumArgs)
+	: byteAt((theFPAbove + FoxIFrameFlags) + 1))))) + BytesPerWord;

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list