[Vm-dev] [commit][3041] CogVM source as per VMMaker.oscog-eem.820

commits at squeakvm.org commits at squeakvm.org
Tue Jul 15 19:11:04 UTC 2014


Revision: 3041
Author:   eliot
Date:     2014-07-15 12:11:00 -0700 (Tue, 15 Jul 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.820

Put the handling of the cloning of cogged methods in the clone: implementations,
removing it from the primitive.  Add it to the pinning clone too.

Specialize the store check trampoline generation.
Move it down to the relevant object representations.

Move setting of isRemembered flag to true into SpurGenerationScavenger>>
remember:.  Inline possibleRootStoreInto: (given that remember: is /not/
 inlined.  Call remember directly from the ceStoreCheckTrampoline, and
 hence have remember: answer its argument.

Fix localization bug.  Variables in initialize methods were not considered
references (cuz there are excluded).  This caused VMMaker.oscog-eem.816's
extraction of zero/false vars to StackInterpreter>>#initialize to cause
nextPollUsecs to be localized to checkForEventsMayContextSwitch:.

Spur:
Fix bug in scanClassPostBecome:effects: with new lazy
selector following policy by... throwing it all away.

The read barriers on method lookup (of the methodClass association in super
sends, of the superclass link, of method dictionaries, method dictionary arrays,
selectors and methods is cheap.  So replace scanning classes and method
dictionaries in the class table post become with read marriewrs on methodClass,
superclass and method dictionary etc on lookup.

The read barrier on an object from which we are going to fetch state (such as a
class or method dictionary) is essentially free on modern machines because the
class index and the state very likely share a cache line, and the register code
for testing is so cheap compared to memory access.  Further the read barrier on
selectors is cheap because the method lookup cache is effective in reducing the
number of message lookups and because nil entries need no check.

So nuke all the followNecessaryForwardingInMethod: machinery including the
cmUsesMethodClass hack.  Nuke scanClassPostBecome:effects:.

Rip out the forwardingCount: measurement code.  It causes
bad performance regressions (due to failing inlines?)

Clean up, e.g. replace followNonImmediateField:ofObject:
uses with followObjField:ofObject:.

canPinObjects can be inlined.

Modified Paths:
--------------
    branches/Cog/nscogsrc/vm/cogit.c
    branches/Cog/nscogsrc/vm/cogit.h
    branches/Cog/nscogsrc/vm/cogmethod.h
    branches/Cog/nscogsrc/vm/cointerp.c
    branches/Cog/nscogsrc/vm/cointerp.h
    branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
    branches/Cog/nscogsrc/vm/interp.h
    branches/Cog/nscogsrc/vm/vmCallback.h
    branches/Cog/nsspursrc/vm/cogit.c
    branches/Cog/nsspursrc/vm/cogit.h
    branches/Cog/nsspursrc/vm/cogmethod.h
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/interp.h
    branches/Cog/nsspursrc/vm/vmCallback.h
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/nsspurstacksrc/vm/interp.h
    branches/Cog/nsspurstacksrc/vm/vmCallback.h
    branches/Cog/sistasrc/vm/cogit.c
    branches/Cog/sistasrc/vm/cogit.h
    branches/Cog/sistasrc/vm/cogmethod.h
    branches/Cog/sistasrc/vm/cointerp.c
    branches/Cog/sistasrc/vm/cointerp.h
    branches/Cog/sistasrc/vm/gcc3x-cointerp.c
    branches/Cog/sistasrc/vm/interp.h
    branches/Cog/sistasrc/vm/vmCallback.h
    branches/Cog/spursistasrc/vm/cogit.c
    branches/Cog/spursistasrc/vm/cogit.h
    branches/Cog/spursistasrc/vm/cogmethod.h
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/interp.h
    branches/Cog/spursistasrc/vm/vmCallback.h
    branches/Cog/spursrc/vm/cogit.c
    branches/Cog/spursrc/vm/cogit.h
    branches/Cog/spursrc/vm/cogmethod.h
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/interp.h
    branches/Cog/spursrc/vm/vmCallback.h
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.c
    branches/Cog/spurstacksrc/vm/interp.h
    branches/Cog/spurstacksrc/vm/vmCallback.h
    branches/Cog/src/vm/cogit.c
    branches/Cog/src/vm/cogit.h
    branches/Cog/src/vm/cogmethod.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/src/vm/interp.h
    branches/Cog/src/vm/vmCallback.h
    branches/Cog/stacksrc/vm/gcc3x-interp.c
    branches/Cog/stacksrc/vm/interp.c
    branches/Cog/stacksrc/vm/interp.h
    branches/Cog/stacksrc/vm/vmCallback.h

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

Modified: branches/Cog/nscogsrc/vm/cogit.c
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.c	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/cogit.c	2014-07-15 19:11:00 UTC (rev 3041)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGenerator VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	StackToRegisterMappingCogit VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4 " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7 " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -809,7 +809,6 @@
 static sqInt roomOnYoungReferrersList(void);
 static void voidYoungReferrersPostTenureAll(void);
 char * whereIsMaybeCodeThing(sqInt anOop);
-static sqInt canPinObjects(void);
 static sqInt checkValidObjectReference(sqInt anOop) NoDbgRegParms;
 static sqInt createsClosuresInline(void);
 static sqInt genEnsureObjInRegNotForwardedscratchReg(sqInt reg, sqInt scratch) NoDbgRegParms;
@@ -2035,7 +2034,6 @@
 static sqInt trampolineTableIndex;
 static sqInt uncheckedEntryAlignment;
 static usqInt unpairedMethodList;
-static sqInt usesMethodClass;
 static usqInt youngReferrers;
 
 
@@ -10692,7 +10690,6 @@
 	(method->cmUsageCount = initialMethodUsageCount());
 	(method->cpicHasMNUCase = 0);
 	(method->cmUsesPenultimateLit = maxLitIndex >= ((literalCountOfHeader(methodHeader)) - 2));
-	(method->cmUsesMethodClass = usesMethodClass);
 	(method->blockEntryOffset = (blockEntryLabel != null
 		? ((blockEntryLabel->address)) - (((sqInt)method))
 		: 0));
@@ -15511,16 +15508,7 @@
 	return null;
 }
 
-
-/*	Answer if the memory manager supports pinned objects. */
-
 static sqInt
-canPinObjects(void)
-{
-	return 0;
-}
-
-static sqInt
 checkValidObjectReference(sqInt anOop)
 {
 	return (!(isImmediate(anOop)))
@@ -15848,6 +15836,12 @@
 	return 0;
 }
 
+
+/*	Do the store check. Answer the argument for the benefit of the code
+	generator; ReceiverResultReg may be caller-saved and hence smashed by this
+	call. Answering
+	it allows the code generator to reload ReceiverResultReg cheaply. */
+
 static void
 generateObjectRepresentationTrampolines(void)
 {
@@ -19032,7 +19026,6 @@
 	primInvokeLabel = null;
 	postCompileHook = null;
 	maxLitIndex = -1;
-	usesMethodClass = 0;
 	extra = ((((primitiveIndex = primitiveIndexOf(methodObj))) > 0)
 	 && (!(isQuickPrimitiveIndex(primitiveIndex)))
 		? 30
@@ -20034,7 +20027,6 @@
 	/* begin MoveCw:R: */
 	genoperandoperand(MoveCwR, selector, ClassReg);
 	CallSend(dynamicSuperSendTrampolines[((numArgs < (NumSendTrampolines - 1)) ? numArgs : (NumSendTrampolines - 1))]);
-	usesMethodClass = 1;
 	(optStatus.isReceiverResultRegLive = 0);
 	return ssPushRegister(ReceiverResultReg);
 }
@@ -20053,7 +20045,6 @@
 	/* begin MoveCw:R: */
 	genoperandoperand(MoveCwR, selector, ClassReg);
 	CallSend(superSendTrampolines[((numArgs < (NumSendTrampolines - 1)) ? numArgs : (NumSendTrampolines - 1))]);
-	usesMethodClass = 1;
 	(optStatus.isReceiverResultRegLive = 0);
 	return ssPushRegister(ReceiverResultReg);
 }

Modified: branches/Cog/nscogsrc/vm/cogit.h
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.h	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/cogit.h	2014-07-15 19:11:00 UTC (rev 3041)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGenerator VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
 
 

Modified: branches/Cog/nscogsrc/vm/cogmethod.h
===================================================================
--- branches/Cog/nscogsrc/vm/cogmethod.h	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/cogmethod.h	2014-07-15 19:11:00 UTC (rev 3041)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGenerator VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
 
 typedef struct {
@@ -11,8 +11,7 @@
 	unsigned		cpicHasMNUCase : 1;
 	unsigned		cmUsageCount : 3;
 	unsigned		cmUsesPenultimateLit : 1;
-	unsigned		cmUsesMethodClass : 1;
-	unsigned		cmUnusedFlags : 2;
+	unsigned		cmUnusedFlags : 3;
 	unsigned		stackCheckOffset : 12;
  } CogBlockMethod;
 
@@ -24,8 +23,7 @@
 	unsigned		cpicHasMNUCase : 1;
 	unsigned		cmUsageCount : 3;
 	unsigned		cmUsesPenultimateLit : 1;
-	unsigned		cmUsesMethodClass : 1;
-	unsigned		cmUnusedFlags : 2;
+	unsigned		cmUnusedFlags : 3;
 	unsigned		stackCheckOffset : 12;
 	unsigned short	blockSize;
 	unsigned short	blockEntryOffset;

Modified: branches/Cog/nscogsrc/vm/cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.c	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/cointerp.c	2014-07-15 19:11:00 UTC (rev 3041)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
    from
-	CoInterpreter VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CoInterpreter VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -534,7 +534,6 @@
 static sqInt voidVMStateForSnapshotFlushingExternalPrimitivesIf(sqInt flushExtPrims) NoDbgRegParms;
 char * whereIs(sqInt anOop);
 static sqInt frameIsMarked(sqInt theFPInt) NoDbgRegParms;
-static void primitiveClone(void);
 static void primitiveClosureCopyWithCopiedValues(void);
 static void primitiveCollectCogCodeConstituents(void);
 static void primitiveContextXray(void);
@@ -836,7 +835,7 @@
 void printWronglySizedContexts(sqInt printContexts);
 static void restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut) NoDbgRegParms;
 static void runLeakCheckerForFullGC(sqInt fullGCFlag) NoDbgRegParms;
-static sqInt safeObjectAfter(sqInt oop) NoDbgRegParms;
+static usqInt safeObjectAfter(sqInt oop) NoDbgRegParms;
 static sqInt safePrintStringOf(sqInt oop) NoDbgRegParms;
 static sqInt shortentoIndexableSize(sqInt obj, sqInt nSlots) NoDbgRegParms;
 static sqInt sizeBitsOfSafe(sqInt oop) NoDbgRegParms;
@@ -1058,7 +1057,7 @@
 double floatArg(sqInt index);
 sqInt floatObjectOf(double aFloat);
 double floatValueOf(sqInt oop);
-static void followNecessaryForwardingInMethod(sqInt methodObj) NoDbgRegParms;
+sqInt followLiteralofMethod(sqInt offset, sqInt methodPointer);
 sqInt forceInterruptCheck(void);
 static char * frameCallerFP(char *theFP) NoDbgRegParms;
 static char * frameCallerSavedIP(char *theFP) NoDbgRegParms;
@@ -1258,6 +1257,7 @@
 static sqInt fieldOrSenderFPofContext(sqInt index, sqInt contextObj) NoDbgRegParms;
 static sqInt fieldofFrame(sqInt index, char *theFP) NoDbgRegParms;
 static sqInt isFrameonPage(char *aFrame, StackPage *aPage) NoDbgRegParms;
+static void primitiveClone(void);
 static void primitiveContextAt(void);
 static void primitiveContextAtPut(void);
 static void primitiveContextSize(void);
@@ -1397,6 +1397,7 @@
 _iss sqInt interruptKeycode;
 _iss sqInt interruptPending;
 _iss usqInt memory;
+_iss usqLong nextPollUsecs;
 _iss usqLong statForceInterruptCheck;
 _iss usqLong statIGCDeltaUsecs;
 _iss sqInt statPendingFinalizationSignals;
@@ -1405,6 +1406,7 @@
 _iss usqLong statStackPageDivorce;
 _iss sqInt deferSmash;
 _iss sqInt deferredSmash;
+_iss sqInt extraFramesToMoveOnOverflow;
 _iss sqInt gcBiasToGrow;
 _iss sqInt gcBiasToGrowGCLimit;
 _iss sqInt globalSessionID;
@@ -1422,6 +1424,7 @@
 _iss sqInt imageHeaderFlags;
 _iss usqLong longRunningPrimitiveGCUsecs;
 _iss sqInt overflowLimit;
+_iss StackPage * overflowedPage;
 _iss sqInt the2ndUnknownShort;
 _iss long methodCache[MethodCacheSize + 1 /* 4097 */];
 _iss sqInt atCache[AtCacheTotalSize + 1 /* 65 */];
@@ -2063,7 +2066,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.816";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.820";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -16389,11 +16392,10 @@
 	probe, since notionally objects' internals are accessed only via sending
 	messages to them,
 	the exception is primitives that access the internals of the non-receiver
-	argument(s). To avoid a read barrier on bytecode, literal and inst var
-	fetch we scan the receivers and
-	methods in the stack zone and follow any forwarded ones. This is of course
-	way cheaper
-	than scanning all of memory as in the old become. */
+	argument(s). To avoid a read barrier on inst var fetch we scan the
+	receivers in the stack zone and follow
+	any forwarded ones. This is way cheaper than scanning all of memory as in
+	the old become. */
 
 static void
 followForwardingPointersInStackZone(sqInt theBecomeEffectsFlags)
@@ -16460,7 +16462,6 @@
 					oop = longAt(theFP + FoxMethod);
 					
 				}
-				followNecessaryForwardingInMethod(oop);
 				if (!(((callerFP = frameCallerFP(theFP))) != 0)) break;
 				theIPPtr = ((usqInt)(theFP + FoxCallerSavedIP));
 				theFP = callerFP;
@@ -16923,7 +16924,7 @@
 		index = 0;
 		while (index <= mask) {
 			nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -16950,7 +16951,7 @@
 			found = 0;
 			goto l1;
 		}
-		/* begin followMaybeForwardedSelector:into: */
+		
 		if (nextSelector == GIV(messageSelector)) {
 			methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 			GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -17019,7 +17020,7 @@
 				index1 = 0;
 				while (index1 <= mask1) {
 					nextSelector1 = longAt((dictionary1 + BaseHeaderSize) + ((index1 + SelectorStart) << ShiftForWord));
-					/* begin followMaybeForwardedSelector:into: */
+					
 					if (nextSelector1 == GIV(messageSelector)) {
 						methodArray1 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 						GIV(newMethod) = longAt((methodArray1 + BaseHeaderSize) + (index1 << ShiftForWord));
@@ -17046,7 +17047,7 @@
 					found1 = 0;
 					goto l2;
 				}
-				/* begin followMaybeForwardedSelector:into: */
+				
 				if (nextSelector1 == GIV(messageSelector)) {
 					methodArray1 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 					GIV(newMethod) = longAt((methodArray1 + BaseHeaderSize) + ((index1 - SelectorStart) << ShiftForWord));
@@ -17298,7 +17299,6 @@
 		? (theIP >> 1)
 		: HasBeenReturnedFromMCPC);
 	theMethod = longAt((aContext + BaseHeaderSize) + (MethodIndex << ShiftForWord));
-	followNecessaryForwardingInMethod(theMethod);
 	/* begin newStackPage */
 	lruOrFree = ((mostRecentlyUsedPage())->nextPage);
 	if (isFree(lruOrFree)) {
@@ -18048,7 +18048,7 @@
 				mnuMethod = null;
 				goto l1;
 			}
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == mnuSelector) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				mnuMethod = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -21062,115 +21062,6 @@
 }
 
 
-/*	Return a shallow copy of the receiver.
-	Special-case non-single contexts (because of context-to-stack mapping).
-	Can't fail for contexts cuz of image context instantiation code (sigh).
-	Special case CompiledMerhods since the copy mustn't refer to CogMethod
-	if receiver has been cogged. */
-
-static void
-primitiveClone(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt cloned;
-    sqInt cogMethodOrMethodHeader;
-    sqInt frameNumArgs;
-    sqInt frameNumArgs1;
-    sqInt header;
-    sqInt i;
-    sqInt methodHeader;
-    sqInt newCopy;
-    sqInt objHeader;
-    sqInt rcvr;
-    sqInt senderOop;
-    char *sp;
-    sqInt sp1;
-    char *spouseFP;
-    sqInt sz;
-    sqInt sz1;
-    sqInt valuePointer;
-    sqInt valuePointer1;
-
-	rcvr = longAt(GIV(stackPointer));
-	if ((rcvr & 1)) {
-		newCopy = rcvr;
-	}
-	else {
-		objHeader = longAt(rcvr);
-		if (((((usqInt) objHeader) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex) {
-			/* begin cloneContext: */
-			/* begin numSlotsOf: */
-			header = longAt(rcvr);
-			sz1 = ((header & TypeMask) == HeaderTypeSizeAndClass
-				? (longAt(rcvr - (BytesPerWord * 2))) & AllButTypeMask
-				: header & SizeMask);
-			sz = ((usqInt) (sz1 - BaseHeaderSize)) >> ShiftForWord;
-			cloned = eeInstantiateMethodContextSlots(sz);
-			if (cloned != 0) {
-				for (i = 0; i <= StackPointerIndex; i += 1) {
-					/* begin storePointerUnchecked:ofObject:withValue: */
-					valuePointer = externalInstVarofContext(i, rcvr);
-					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), valuePointer);
-				}
-				for (i = MethodIndex; i <= ReceiverIndex; i += 1) {
-					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), longAt((rcvr + BaseHeaderSize) + (i << ShiftForWord)));
-				}
-				if ((((longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord))) & 1))
-				 && (!(isWidowedContext(rcvr)))) {
-					/* begin frameOfMarriedContext: */
-					senderOop = longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord));
-					/* begin withoutSmallIntegerTags: */
-					assert((senderOop & 1));
-					spouseFP = pointerForOop(senderOop - 1);
-					sp1 = (stackPointerIndexForFrame(spouseFP)) - 1;
-					for (i = 0; i <= sp1; i += 1) {
-						/* begin storePointerUnchecked:ofObject:withValue: */
-						valuePointer1 = ((((usqInt)(longAt(spouseFP + FoxMethod)))) < (startOfMemory())
-							? (i < ((frameNumArgs = ((mframeCogMethod(spouseFP))->cmNumArgs)))
-									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs - i) * BytesPerWord))
-									: longAt(((spouseFP + FoxMFReceiver) - BytesPerWord) + ((frameNumArgs - i) * BytesPerWord)))
-							: (i < ((frameNumArgs1 = byteAt((spouseFP + FoxIFrameFlags) + 1)))
-									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs1 - i) * BytesPerWord))
-									: longAt(((spouseFP + FoxIFReceiver) - BytesPerWord) + ((frameNumArgs1 - i) * BytesPerWord))));
-						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), valuePointer1);
-					}
-				}
-				else {
-					sp1 = (fetchStackPointerOf(rcvr)) - 1;
-					for (i = 0; i <= sp1; i += 1) {
-						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), longAt((rcvr + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord)));
-					}
-				}
-			}
-			newCopy = cloned;
-		}
-		else {
-			newCopy = clone(rcvr);
-		}
-		if (newCopy == 0) {
-			(GIV(primFailCode) = PrimErrNoMemory);
-			return;
-		}
-		if (((((usqInt) objHeader) >> (instFormatFieldLSB())) & 15) >= 12) {
-
-			/* use stackTop since GC may have moved rcvr */
-
-			/* begin rawHeaderOf:put: */
-			/* begin headerOf: */
-			methodHeader = longAt(((longAt(GIV(stackPointer))) + BaseHeaderSize) + (HeaderIndex << ShiftForWord));
-			cogMethodOrMethodHeader = (isCogMethodReference(methodHeader)
-				? (assert((((((CogMethod *) methodHeader))->objectHeader)) == (nullHeaderForMachineCodeMethod())),
-					((((CogMethod *) methodHeader))->methodHeader))
-				: methodHeader);
-			assert(isCompiledMethodHeader(headerWhileForwardingOf(newCopy)));
-			longAtput((newCopy + BaseHeaderSize) + (HeaderIndex << ShiftForWord), cogMethodOrMethodHeader);
-		}
-	}
-	/* begin pop:thenPush: */
-	longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), newCopy);
-	GIV(stackPointer) = sp;
-}
-
-
 /*	This is optional old obsolete stuff tedious to implement in Cog because of
 	the need to map from machine code pc to bytecode pc. So for now just fail. */
 
@@ -35803,16 +35694,16 @@
 }
 
 
-/*	Return a shallow copy of the given object. May cause GC */
-/*	Assume: Oop is a real object, not a small integer. */
-/*	Return a shallow copy of the given object. May cause GC */
-/*	Assume: Oop is a real object, not a small integer.
-	Override to assert it's not a married context */
+/*	Return a shallow copy of the given object. May cause GC.
+	Assume: Oop is a real object, not a small integer.
+	Override to assert it's not a married context and maybe fix cloned
+	methods.  */
 
 sqInt
 clone(sqInt obj)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt bytes;
+    sqInt cogMethodOrMethodHeader;
     sqInt extraHdrBytes;
     usqInt fromIndex;
     sqInt hash;
@@ -35824,6 +35715,7 @@
     usqInt newFreeStart;
     sqInt newOop;
     sqInt oop;
+    sqInt rawHeader;
     sqInt remappedOop;
     sqInt toIndex;
 
@@ -35892,6 +35784,17 @@
 	header = (longAt(newOop)) & 0x1FFFF;
 	header = header | ((hash << HashBitsOffset) & HashBits);
 	longAtput(newOop, header);
+	if (((((usqInt) header) >> (instFormatFieldLSB())) & 15) >= 12) {
+		/* begin maybeFixClonedCompiledMethod: */
+		assert(isOopCompiledMethod(newOop));
+		rawHeader = longAt((newOop + BaseHeaderSize) + (HeaderIndex << ShiftForWord));
+		if (isCogMethodReference(rawHeader)) {
+			/* begin rawHeaderOf:put: */
+			cogMethodOrMethodHeader = ((((CogMethod *) rawHeader))->methodHeader);
+			assert(isCompiledMethodHeader(headerWhileForwardingOf(newOop)));
+			longAtput((newOop + BaseHeaderSize) + (HeaderIndex << ShiftForWord), cogMethodOrMethodHeader);
+		}
+	}
 	return newOop;
 }
 
@@ -36982,17 +36885,15 @@
     sqInt header1;
     sqInt header2;
     sqInt header3;
-    sqInt header4;
     usqInt lastWord;
     sqInt newFreeChunk;
     sqInt newOop;
-    sqInt next;
+    usqInt next;
     sqInt oop;
     sqInt realHeader;
     sqInt sz;
     sqInt sz1;
     sqInt sz2;
-    sqInt sz3;
     sqInt target;
     usqInt w;
 
@@ -37003,21 +36904,7 @@
 		/* begin objectAfterWhileForwarding: */
 		header2 = longAt(oop);
 		if ((header2 & MarkBit) == 0) {
-			/* begin objectAfter: */
-			if (!(asserta(oopisLessThan(oop, GIV(freeStart))))) {
-				error("no objects after the end of memory");
-			}
-			if (((longAt(oop)) & TypeMask) == HeaderTypeFree) {
-				sz2 = (longAt(oop)) & AllButTypeMask;
-			}
-			else {
-				/* begin sizeBitsOf: */
-				header3 = longAt(oop);
-				sz2 = ((header3 & TypeMask) == HeaderTypeSizeAndClass
-					? (longAt(oop - (BytesPerWord * 2))) & LongSizeMask
-					: header3 & SizeMask);
-			}
-			next = (oop + sz2) + (headerTypeBytes[(longAt(oop + sz2)) & TypeMask]);
+			next = ((sqInt) (objectAfter(oop)));
 			goto l1;
 		}
 		fwdBlock1 = (header2 & AllButMarkBitAndTypeMask) << 1;
@@ -37032,7 +36919,7 @@
 		else {
 			sz1 = realHeader & SizeMask;
 		}
-		next = (oop + sz1) + (headerTypeBytes[(longAt(oop + sz1)) & TypeMask]);
+		next = ((sqInt) ((oop + sz1) + (headerTypeBytes[(longAt(oop + sz1)) & TypeMask])));
 	l1:	/* end objectAfterWhileForwarding: */;
 		if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) {
 
@@ -37086,18 +36973,18 @@
 	}
 	/* begin safeObjectAfter: */
 	if (((longAt(newFreeChunk)) & TypeMask) == HeaderTypeFree) {
-		sz3 = (longAt(newFreeChunk)) & AllButTypeMask;
+		sz2 = (longAt(newFreeChunk)) & AllButTypeMask;
 	}
 	else {
 		/* begin sizeBitsOf: */
-		header4 = longAt(newFreeChunk);
-		sz3 = ((header4 & TypeMask) == HeaderTypeSizeAndClass
+		header3 = longAt(newFreeChunk);
+		sz2 = ((header3 & TypeMask) == HeaderTypeSizeAndClass
 			? (longAt(newFreeChunk - (BytesPerWord * 2))) & LongSizeMask
-			: header4 & SizeMask);
+			: header3 & SizeMask);
 	}
-	next = ((newFreeChunk + sz3) >= GIV(freeStart)
+	next = ((newFreeChunk + sz2) >= GIV(freeStart)
 		? GIV(freeStart)
-		: (newFreeChunk + sz3) + (headerTypeBytes[(longAt(newFreeChunk + sz3)) & TypeMask]));
+		: (newFreeChunk + sz2) + (headerTypeBytes[(longAt(newFreeChunk + sz2)) & TypeMask]));
 	assert((next == GIV(freeStart))
 	 || (next == (oopFromChunk(GIV(compEnd)))));
 	if (next == GIV(freeStart)) {
@@ -38965,7 +38852,7 @@
 	given object or free chunk in memory. Return freeStart when
 	enumeration is complete. This is for assertion checking only. */
 
-static sqInt
+static usqInt
 safeObjectAfter(sqInt oop)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt header;
@@ -43766,7 +43653,6 @@
 static sqInt
 checkForEventsMayContextSwitch(sqInt mayContextSwitch)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    usqLong nextPollUsecs = 0;
     usqLong now;
     sqInt sema;
     sqInt switched;
@@ -43838,7 +43724,7 @@
 			switched = 1;
 		}
 	}
-	if (((now = ioUTCMicroseconds())) >= nextPollUsecs) {
+	if (((now = ioUTCMicroseconds())) >= GIV(nextPollUsecs)) {
 		GIV(statIOProcessEvents) += 1;
 		ioProcessEvents();
 
@@ -43846,7 +43732,7 @@
 		   speaking we might need to update 'now' at this point since
 		   ioProcessEvents could take a very long time on some platforms */
 
-		nextPollUsecs = now + 20000;
+		GIV(nextPollUsecs) = now + 20000;
 	}
 
 	if (GIV(interruptPending)) {
@@ -45998,21 +45884,10 @@
 	return 0.0;
 }
 
-
-/*	To avoid any chance of a forwarded object during super sends we follow the
-	methodClassAssociation. The forwarded object send fault only copes with
-	normal sends to instances. */
-
-static void
-followNecessaryForwardingInMethod(sqInt methodObj)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt assoc;
-    sqInt classObj;
-    CogMethod *cogMethod;
-    sqInt header;
-    sqInt litCount;
-
-	
+sqInt
+followLiteralofMethod(sqInt offset, sqInt methodPointer)
+{
+	return longAt((methodPointer + BaseHeaderSize) + ((offset + LiteralStart) << ShiftForWord));
 }
 
 
@@ -46274,12 +46149,10 @@
     sqInt callerContextOrNil;
     char *callerFP;
     char *callerFP1;
-    sqInt extraFramesToMoveOnOverflow = 0;
     sqInt index;
     StackPage *lruOrFree;
     StackPage *newPage;
     sqInt overflowCount;
-    StackPage * overflowedPage = 0;
     char *overflowLimitAddress;
     sqInt source;
     char *theFP;
@@ -46315,9 +46188,9 @@
 
 	GIV(statStackOverflow) += 1;
 	theFP = GIV(framePointer);
-	if (GIV(stackPage) == overflowedPage) {
+	if (GIV(stackPage) == GIV(overflowedPage)) {
 		overflowLimitAddress = ((GIV(stackPage)->baseAddress)) - GIV(overflowLimit);
-		overflowCount = (extraFramesToMoveOnOverflow += 1);
+		overflowCount = (GIV(extraFramesToMoveOnOverflow) += 1);
 		while ((((overflowCount -= 1)) >= 0)
 		 && ((((callerFP = frameCallerFP(theFP))) < overflowLimitAddress)
 		 && (!((longAt(callerFP + FoxSavedFP)) == 0)))) {
@@ -46325,8 +46198,8 @@
 		}
 	}
 	else {
-		overflowedPage = GIV(stackPage);
-		extraFramesToMoveOnOverflow = 0;
+		GIV(overflowedPage) = GIV(stackPage);
+		GIV(extraFramesToMoveOnOverflow) = 0;
 	}
 	/* begin ensureCallerContext: */
 	/* begin frameCallerFP: */
@@ -47280,7 +47153,7 @@
 			index = 0;
 			while (index <= mask) {
 				nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-				/* begin followMaybeForwardedSelector:into: */
+				
 				if (nextSelector == GIV(messageSelector)) {
 					methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 					GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -47307,7 +47180,7 @@
 				found = 0;
 				goto l1;
 			}
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -47374,7 +47247,7 @@
 		index = 0;
 		while (index <= mask) {
 			nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -47398,7 +47271,7 @@
 		if (nextSelector == GIV(nilObj)) {
 			return 0;
 		}
-		/* begin followMaybeForwardedSelector:into: */
+		
 		if (nextSelector == GIV(messageSelector)) {
 			methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 			GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -48029,6 +47902,13 @@
 	return longAt((methodPointer + BaseHeaderSize) + ((offset + LiteralStart) << ShiftForWord));
 }
 
+
+/*	Using a read barrier here simplifies the become implementation and costs
+	very little
+	because the class index and ValueIndex of the association almost certainly
+	share a cache line.
+ */
+
 sqInt
 methodClassOf(sqInt methodPointer)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
@@ -48036,10 +47916,9 @@
     sqInt offset;
     sqInt offset1;
 
-	return (/* begin literal:ofMethod: */
+	return (/* begin followLiteral:ofMethod: */
 			(offset = (literalCountOfHeader(headerOf(methodPointer))) - 1),
 			(literal = longAt((methodPointer + BaseHeaderSize) + ((offset + LiteralStart) << ShiftForWord))),
-			assert(!(isForwarded(literal))),
 			(literal == GIV(nilObj)
 					? literal
 					: longAt((literal + BaseHeaderSize) + (ValueIndex << ShiftForWord))));
@@ -52214,6 +52093,11 @@
 	return totalLength - fixedFields;
 }
 
+
+/*	Using a read barrier here simplifies the become implementation and costs
+	very little because the class index and superclass almost certainly share
+	a cache line. */
+
 sqInt
 superclassOf(sqInt classPointer)
 {
@@ -52595,6 +52479,95 @@
 }
 
 
+/*	Return a shallow copy of the receiver.
+	Special-case non-single contexts (because of context-to-stack mapping).
+	Can't fail for contexts cuz of image context instantiation code (sigh). */
+
+static void
+primitiveClone(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt cloned;
+    sqInt frameNumArgs;
+    sqInt frameNumArgs1;
+    sqInt header;
+    sqInt i;
+    sqInt newCopy;
+    sqInt rcvr;
+    sqInt senderOop;
+    char *sp;
+    sqInt sp1;
+    char *spouseFP;
+    sqInt sz;
+    sqInt sz1;
+    sqInt valuePointer;
+    sqInt valuePointer1;
+
+	rcvr = longAt(GIV(stackPointer));
+	if ((rcvr & 1)) {
+		newCopy = rcvr;
+	}
+	else {
+		if (((((usqInt) (longAt(rcvr))) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex) {
+			/* begin cloneContext: */
+			/* begin numSlotsOf: */
+			header = longAt(rcvr);
+			sz1 = ((header & TypeMask) == HeaderTypeSizeAndClass
+				? (longAt(rcvr - (BytesPerWord * 2))) & AllButTypeMask
+				: header & SizeMask);
+			sz = ((usqInt) (sz1 - BaseHeaderSize)) >> ShiftForWord;
+			cloned = eeInstantiateMethodContextSlots(sz);
+			if (cloned != 0) {
+				for (i = 0; i <= StackPointerIndex; i += 1) {
+					/* begin storePointerUnchecked:ofObject:withValue: */
+					valuePointer = externalInstVarofContext(i, rcvr);
+					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), valuePointer);
+				}
+				for (i = MethodIndex; i <= ReceiverIndex; i += 1) {
+					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), longAt((rcvr + BaseHeaderSize) + (i << ShiftForWord)));
+				}
+				if ((((longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord))) & 1))
+				 && (!(isWidowedContext(rcvr)))) {
+					/* begin frameOfMarriedContext: */
+					senderOop = longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord));
+					/* begin withoutSmallIntegerTags: */
+					assert((senderOop & 1));
+					spouseFP = pointerForOop(senderOop - 1);
+					sp1 = (stackPointerIndexForFrame(spouseFP)) - 1;
+					for (i = 0; i <= sp1; i += 1) {
+						/* begin storePointerUnchecked:ofObject:withValue: */
+						valuePointer1 = ((((usqInt)(longAt(spouseFP + FoxMethod)))) < (startOfMemory())
+							? (i < ((frameNumArgs = ((mframeCogMethod(spouseFP))->cmNumArgs)))
+									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs - i) * BytesPerWord))
+									: longAt(((spouseFP + FoxMFReceiver) - BytesPerWord) + ((frameNumArgs - i) * BytesPerWord)))
+							: (i < ((frameNumArgs1 = byteAt((spouseFP + FoxIFrameFlags) + 1)))
+									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs1 - i) * BytesPerWord))
+									: longAt(((spouseFP + FoxIFReceiver) - BytesPerWord) + ((frameNumArgs1 - i) * BytesPerWord))));
+						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), valuePointer1);
+					}
+				}
+				else {
+					sp1 = (fetchStackPointerOf(rcvr)) - 1;
+					for (i = 0; i <= sp1; i += 1) {
+						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), longAt((rcvr + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord)));
+					}
+				}
+			}
+			newCopy = cloned;
+		}
+		else {
+			newCopy = clone(rcvr);
+		}
+		if (newCopy == 0) {
+			(GIV(primFailCode) = PrimErrNoMemory);
+			return;
+		}
+	}
+	/* begin pop:thenPush: */
+	longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), newCopy);
+	GIV(stackPointer) = sp;
+}
+
+
 /*	Special version of primitiveAt for accessing contexts.
 	Written to be varargs for use from mirror primitives. */
 

Modified: branches/Cog/nscogsrc/vm/cointerp.h
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.h	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/cointerp.h	2014-07-15 19:11:00 UTC (rev 3041)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
 
 
@@ -205,6 +205,7 @@
 sqInt checkOkayInterpreterObjects(sqInt writeBack);
 sqInt copiedValueCountOfClosure(sqInt closurePointer);
 sqInt doSignalSemaphoreWithIndex(sqInt index);
+sqInt followLiteralofMethod(sqInt offset, sqInt methodPointer);
 void (*functionPointerForinClass(sqInt primIdx,sqInt theClass))(void) ;
 usqLong getNextWakeupUsecs(void);
 sqInt * getStackPointer(void);

Modified: branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-07-11 17:25:27 UTC (rev 3040)
+++ branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-07-15 19:11:00 UTC (rev 3041)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
    from
-	CoInterpreter VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4
+	CoInterpreter VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.816 uuid: 33bf745c-6348-4ad4-9ad3-bec0373bacd4 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.820 uuid: 783c4789-0cac-41f9-9b01-d1930e0fe4d7 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -537,7 +537,6 @@
 static sqInt voidVMStateForSnapshotFlushingExternalPrimitivesIf(sqInt flushExtPrims) NoDbgRegParms;
 char * whereIs(sqInt anOop);
 static sqInt frameIsMarked(sqInt theFPInt) NoDbgRegParms;
-static void primitiveClone(void);
 static void primitiveClosureCopyWithCopiedValues(void);
 static void primitiveCollectCogCodeConstituents(void);
 static void primitiveContextXray(void);
@@ -839,7 +838,7 @@
 void printWronglySizedContexts(sqInt printContexts);
 static void restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut) NoDbgRegParms;
 static void runLeakCheckerForFullGC(sqInt fullGCFlag) NoDbgRegParms;
-static sqInt safeObjectAfter(sqInt oop) NoDbgRegParms;
+static usqInt safeObjectAfter(sqInt oop) NoDbgRegParms;
 static sqInt safePrintStringOf(sqInt oop) NoDbgRegParms;
 static sqInt shortentoIndexableSize(sqInt obj, sqInt nSlots) NoDbgRegParms;
 static sqInt sizeBitsOfSafe(sqInt oop) NoDbgRegParms;
@@ -1061,7 +1060,7 @@
 double floatArg(sqInt index);
 sqInt floatObjectOf(double aFloat);
 double floatValueOf(sqInt oop);
-static void followNecessaryForwardingInMethod(sqInt methodObj) NoDbgRegParms;
+sqInt followLiteralofMethod(sqInt offset, sqInt methodPointer);
 sqInt forceInterruptCheck(void);
 static char * frameCallerFP(char *theFP) NoDbgRegParms;
 static char * frameCallerSavedIP(char *theFP) NoDbgRegParms;
@@ -1261,6 +1260,7 @@
 static sqInt fieldOrSenderFPofContext(sqInt index, sqInt contextObj) NoDbgRegParms;
 static sqInt fieldofFrame(sqInt index, char *theFP) NoDbgRegParms;
 static sqInt isFrameonPage(char *aFrame, StackPage *aPage) NoDbgRegParms;
+static void primitiveClone(void);
 static void primitiveContextAt(void);
 static void primitiveContextAtPut(void);
 static void primitiveContextSize(void);
@@ -1400,6 +1400,7 @@
 _iss sqInt interruptKeycode;
 _iss sqInt interruptPending;
 _iss usqInt memory;
+_iss usqLong nextPollUsecs;
 _iss usqLong statForceInterruptCheck;
 _iss usqLong statIGCDeltaUsecs;
 _iss sqInt statPendingFinalizationSignals;
@@ -1408,6 +1409,7 @@
 _iss usqLong statStackPageDivorce;
 _iss sqInt deferSmash;
 _iss sqInt deferredSmash;
+_iss sqInt extraFramesToMoveOnOverflow;
 _iss sqInt gcBiasToGrow;
 _iss sqInt gcBiasToGrowGCLimit;
 _iss sqInt globalSessionID;
@@ -1425,6 +1427,7 @@
 _iss sqInt imageHeaderFlags;
 _iss usqLong longRunningPrimitiveGCUsecs;
 _iss sqInt overflowLimit;
+_iss StackPage * overflowedPage;
 _iss sqInt the2ndUnknownShort;
 _iss long methodCache[MethodCacheSize + 1 /* 4097 */];
 _iss sqInt atCache[AtCacheTotalSize + 1 /* 65 */];
@@ -2066,7 +2069,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.816";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.820";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -16398,11 +16401,10 @@
 	probe, since notionally objects' internals are accessed only via sending
 	messages to them,
 	the exception is primitives that access the internals of the non-receiver
-	argument(s). To avoid a read barrier on bytecode, literal and inst var
-	fetch we scan the receivers and
-	methods in the stack zone and follow any forwarded ones. This is of course
-	way cheaper
-	than scanning all of memory as in the old become. */
+	argument(s). To avoid a read barrier on inst var fetch we scan the
+	receivers in the stack zone and follow
+	any forwarded ones. This is way cheaper than scanning all of memory as in
+	the old become. */
 
 static void
 followForwardingPointersInStackZone(sqInt theBecomeEffectsFlags)
@@ -16469,7 +16471,6 @@
 					oop = longAt(theFP + FoxMethod);
 					
 				}
-				followNecessaryForwardingInMethod(oop);
 				if (!(((callerFP = frameCallerFP(theFP))) != 0)) break;
 				theIPPtr = ((usqInt)(theFP + FoxCallerSavedIP));
 				theFP = callerFP;
@@ -16932,7 +16933,7 @@
 		index = 0;
 		while (index <= mask) {
 			nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -16959,7 +16960,7 @@
 			found = 0;
 			goto l1;
 		}
-		/* begin followMaybeForwardedSelector:into: */
+		
 		if (nextSelector == GIV(messageSelector)) {
 			methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 			GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -17028,7 +17029,7 @@
 				index1 = 0;
 				while (index1 <= mask1) {
 					nextSelector1 = longAt((dictionary1 + BaseHeaderSize) + ((index1 + SelectorStart) << ShiftForWord));
-					/* begin followMaybeForwardedSelector:into: */
+					
 					if (nextSelector1 == GIV(messageSelector)) {
 						methodArray1 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 						GIV(newMethod) = longAt((methodArray1 + BaseHeaderSize) + (index1 << ShiftForWord));
@@ -17055,7 +17056,7 @@
 					found1 = 0;
 					goto l2;
 				}
-				/* begin followMaybeForwardedSelector:into: */
+				
 				if (nextSelector1 == GIV(messageSelector)) {
 					methodArray1 = longAt((dictionary1 + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 					GIV(newMethod) = longAt((methodArray1 + BaseHeaderSize) + ((index1 - SelectorStart) << ShiftForWord));
@@ -17307,7 +17308,6 @@
 		? (theIP >> 1)
 		: HasBeenReturnedFromMCPC);
 	theMethod = longAt((aContext + BaseHeaderSize) + (MethodIndex << ShiftForWord));
-	followNecessaryForwardingInMethod(theMethod);
 	/* begin newStackPage */
 	lruOrFree = ((mostRecentlyUsedPage())->nextPage);
 	if (isFree(lruOrFree)) {
@@ -18057,7 +18057,7 @@
 				mnuMethod = null;
 				goto l1;
 			}
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == mnuSelector) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				mnuMethod = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -21071,115 +21071,6 @@
 }
 
 
-/*	Return a shallow copy of the receiver.
-	Special-case non-single contexts (because of context-to-stack mapping).
-	Can't fail for contexts cuz of image context instantiation code (sigh).
-	Special case CompiledMerhods since the copy mustn't refer to CogMethod
-	if receiver has been cogged. */
-
-static void
-primitiveClone(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt cloned;
-    sqInt cogMethodOrMethodHeader;
-    sqInt frameNumArgs;
-    sqInt frameNumArgs1;
-    sqInt header;
-    sqInt i;
-    sqInt methodHeader;
-    sqInt newCopy;
-    sqInt objHeader;
-    sqInt rcvr;
-    sqInt senderOop;
-    char *sp;
-    sqInt sp1;
-    char *spouseFP;
-    sqInt sz;
-    sqInt sz1;
-    sqInt valuePointer;
-    sqInt valuePointer1;
-
-	rcvr = longAt(GIV(stackPointer));
-	if ((rcvr & 1)) {
-		newCopy = rcvr;
-	}
-	else {
-		objHeader = longAt(rcvr);
-		if (((((usqInt) objHeader) >> (compactClassFieldLSB())) & 0x1F) == ClassMethodContextCompactIndex) {
-			/* begin cloneContext: */
-			/* begin numSlotsOf: */
-			header = longAt(rcvr);
-			sz1 = ((header & TypeMask) == HeaderTypeSizeAndClass
-				? (longAt(rcvr - (BytesPerWord * 2))) & AllButTypeMask
-				: header & SizeMask);
-			sz = ((usqInt) (sz1 - BaseHeaderSize)) >> ShiftForWord;
-			cloned = eeInstantiateMethodContextSlots(sz);
-			if (cloned != 0) {
-				for (i = 0; i <= StackPointerIndex; i += 1) {
-					/* begin storePointerUnchecked:ofObject:withValue: */
-					valuePointer = externalInstVarofContext(i, rcvr);
-					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), valuePointer);
-				}
-				for (i = MethodIndex; i <= ReceiverIndex; i += 1) {
-					longAtput((cloned + BaseHeaderSize) + (i << ShiftForWord), longAt((rcvr + BaseHeaderSize) + (i << ShiftForWord)));
-				}
-				if ((((longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord))) & 1))
-				 && (!(isWidowedContext(rcvr)))) {
-					/* begin frameOfMarriedContext: */
-					senderOop = longAt((rcvr + BaseHeaderSize) + (SenderIndex << ShiftForWord));
-					/* begin withoutSmallIntegerTags: */
-					assert((senderOop & 1));
-					spouseFP = pointerForOop(senderOop - 1);
-					sp1 = (stackPointerIndexForFrame(spouseFP)) - 1;
-					for (i = 0; i <= sp1; i += 1) {
-						/* begin storePointerUnchecked:ofObject:withValue: */
-						valuePointer1 = ((((usqInt)(longAt(spouseFP + FoxMethod)))) < (startOfMemory())
-							? (i < ((frameNumArgs = ((mframeCogMethod(spouseFP))->cmNumArgs)))
-									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs - i) * BytesPerWord))
-									: longAt(((spouseFP + FoxMFReceiver) - BytesPerWord) + ((frameNumArgs - i) * BytesPerWord)))
-							: (i < ((frameNumArgs1 = byteAt((spouseFP + FoxIFrameFlags) + 1)))
-									? longAt((spouseFP + FoxCallerSavedIP) + ((frameNumArgs1 - i) * BytesPerWord))
-									: longAt(((spouseFP + FoxIFReceiver) - BytesPerWord) + ((frameNumArgs1 - i) * BytesPerWord))));
-						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), valuePointer1);
-					}
-				}
-				else {
-					sp1 = (fetchStackPointerOf(rcvr)) - 1;
-					for (i = 0; i <= sp1; i += 1) {
-						longAtput((cloned + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord), longAt((rcvr + BaseHeaderSize) + ((i + CtxtTempFrameStart) << ShiftForWord)));
-					}
-				}
-			}
-			newCopy = cloned;
-		}
-		else {
-			newCopy = clone(rcvr);
-		}
-		if (newCopy == 0) {
-			(GIV(primFailCode) = PrimErrNoMemory);
-			return;
-		}
-		if (((((usqInt) objHeader) >> (instFormatFieldLSB())) & 15) >= 12) {
-
-			/* use stackTop since GC may have moved rcvr */
-
-			/* begin rawHeaderOf:put: */
-			/* begin headerOf: */
-			methodHeader = longAt(((longAt(GIV(stackPointer))) + BaseHeaderSize) + (HeaderIndex << ShiftForWord));
-			cogMethodOrMethodHeader = (isCogMethodReference(methodHeader)
-				? (assert((((((CogMethod *) methodHeader))->objectHeader)) == (nullHeaderForMachineCodeMethod())),
-					((((CogMethod *) methodHeader))->methodHeader))
-				: methodHeader);
-			assert(isCompiledMethodHeader(headerWhileForwardingOf(newCopy)));
-			longAtput((newCopy + BaseHeaderSize) + (HeaderIndex << ShiftForWord), cogMethodOrMethodHeader);
-		}
-	}
-	/* begin pop:thenPush: */
-	longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), newCopy);
-	GIV(stackPointer) = sp;
-}
-
-
 /*	This is optional old obsolete stuff tedious to implement in Cog because of
 	the need to map from machine code pc to bytecode pc. So for now just fail. */
 
@@ -35812,16 +35703,16 @@
 }
 
 
-/*	Return a shallow copy of the given object. May cause GC */
-/*	Assume: Oop is a real object, not a small integer. */
-/*	Return a shallow copy of the given object. May cause GC */
-/*	Assume: Oop is a real object, not a small integer.
-	Override to assert it's not a married context */
+/*	Return a shallow copy of the given object. May cause GC.
+	Assume: Oop is a real object, not a small integer.
+	Override to assert it's not a married context and maybe fix cloned
+	methods.  */
 
 sqInt
 clone(sqInt obj)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt bytes;
+    sqInt cogMethodOrMethodHeader;
     sqInt extraHdrBytes;
     usqInt fromIndex;
     sqInt hash;
@@ -35833,6 +35724,7 @@
     usqInt newFreeStart;
     sqInt newOop;
     sqInt oop;
+    sqInt rawHeader;
     sqInt remappedOop;
     sqInt toIndex;
 
@@ -35901,6 +35793,17 @@
 	header = (longAt(newOop)) & 0x1FFFF;
 	header = header | ((hash << HashBitsOffset) & HashBits);
 	longAtput(newOop, header);
+	if (((((usqInt) header) >> (instFormatFieldLSB())) & 15) >= 12) {
+		/* begin maybeFixClonedCompiledMethod: */
+		assert(isOopCompiledMethod(newOop));
+		rawHeader = longAt((newOop + BaseHeaderSize) + (HeaderIndex << ShiftForWord));
+		if (isCogMethodReference(rawHeader)) {
+			/* begin rawHeaderOf:put: */
+			cogMethodOrMethodHeader = ((((CogMethod *) rawHeader))->methodHeader);
+			assert(isCompiledMethodHeader(headerWhileForwardingOf(newOop)));
+			longAtput((newOop + BaseHeaderSize) + (HeaderIndex << ShiftForWord), cogMethodOrMethodHeader);
+		}
+	}
 	return newOop;
 }
 
@@ -36991,17 +36894,15 @@
     sqInt header1;
     sqInt header2;
     sqInt header3;
-    sqInt header4;
     usqInt lastWord;
     sqInt newFreeChunk;
     sqInt newOop;
-    sqInt next;
+    usqInt next;
     sqInt oop;
     sqInt realHeader;
     sqInt sz;
     sqInt sz1;
     sqInt sz2;
-    sqInt sz3;
     sqInt target;
     usqInt w;
 
@@ -37012,21 +36913,7 @@
 		/* begin objectAfterWhileForwarding: */
 		header2 = longAt(oop);
 		if ((header2 & MarkBit) == 0) {
-			/* begin objectAfter: */
-			if (!(asserta(oopisLessThan(oop, GIV(freeStart))))) {
-				error("no objects after the end of memory");
-			}
-			if (((longAt(oop)) & TypeMask) == HeaderTypeFree) {
-				sz2 = (longAt(oop)) & AllButTypeMask;
-			}
-			else {
-				/* begin sizeBitsOf: */
-				header3 = longAt(oop);
-				sz2 = ((header3 & TypeMask) == HeaderTypeSizeAndClass
-					? (longAt(oop - (BytesPerWord * 2))) & LongSizeMask
-					: header3 & SizeMask);
-			}
-			next = (oop + sz2) + (headerTypeBytes[(longAt(oop + sz2)) & TypeMask]);
+			next = ((sqInt) (objectAfter(oop)));
 			goto l1;
 		}
 		fwdBlock1 = (header2 & AllButMarkBitAndTypeMask) << 1;
@@ -37041,7 +36928,7 @@
 		else {
 			sz1 = realHeader & SizeMask;
 		}
-		next = (oop + sz1) + (headerTypeBytes[(longAt(oop + sz1)) & TypeMask]);
+		next = ((sqInt) ((oop + sz1) + (headerTypeBytes[(longAt(oop + sz1)) & TypeMask])));
 	l1:	/* end objectAfterWhileForwarding: */;
 		if (!(((longAt(oop)) & TypeMask) == HeaderTypeFree)) {
 
@@ -37095,18 +36982,18 @@
 	}
 	/* begin safeObjectAfter: */
 	if (((longAt(newFreeChunk)) & TypeMask) == HeaderTypeFree) {
-		sz3 = (longAt(newFreeChunk)) & AllButTypeMask;
+		sz2 = (longAt(newFreeChunk)) & AllButTypeMask;
 	}
 	else {
 		/* begin sizeBitsOf: */
-		header4 = longAt(newFreeChunk);
-		sz3 = ((header4 & TypeMask) == HeaderTypeSizeAndClass
+		header3 = longAt(newFreeChunk);
+		sz2 = ((header3 & TypeMask) == HeaderTypeSizeAndClass
 			? (longAt(newFreeChunk - (BytesPerWord * 2))) & LongSizeMask
-			: header4 & SizeMask);
+			: header3 & SizeMask);
 	}
-	next = ((newFreeChunk + sz3) >= GIV(freeStart)
+	next = ((newFreeChunk + sz2) >= GIV(freeStart)
 		? GIV(freeStart)
-		: (newFreeChunk + sz3) + (headerTypeBytes[(longAt(newFreeChunk + sz3)) & TypeMask]));
+		: (newFreeChunk + sz2) + (headerTypeBytes[(longAt(newFreeChunk + sz2)) & TypeMask]));
 	assert((next == GIV(freeStart))
 	 || (next == (oopFromChunk(GIV(compEnd)))));
 	if (next == GIV(freeStart)) {
@@ -38974,7 +38861,7 @@
 	given object or free chunk in memory. Return freeStart when
 	enumeration is complete. This is for assertion checking only. */
 
-static sqInt
+static usqInt
 safeObjectAfter(sqInt oop)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt header;
@@ -43775,7 +43662,6 @@
 static sqInt
 checkForEventsMayContextSwitch(sqInt mayContextSwitch)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    usqLong nextPollUsecs = 0;
     usqLong now;
     sqInt sema;
     sqInt switched;
@@ -43847,7 +43733,7 @@
 			switched = 1;
 		}
 	}
-	if (((now = ioUTCMicroseconds())) >= nextPollUsecs) {
+	if (((now = ioUTCMicroseconds())) >= GIV(nextPollUsecs)) {
 		GIV(statIOProcessEvents) += 1;
 		ioProcessEvents();
 
@@ -43855,7 +43741,7 @@
 		   speaking we might need to update 'now' at this point since
 		   ioProcessEvents could take a very long time on some platforms */
 
-		nextPollUsecs = now + 20000;
+		GIV(nextPollUsecs) = now + 20000;
 	}
 
 	if (GIV(interruptPending)) {
@@ -46007,21 +45893,10 @@
 	return 0.0;
 }
 
-
-/*	To avoid any chance of a forwarded object during super sends we follow the
-	methodClassAssociation. The forwarded object send fault only copes with
-	normal sends to instances. */
-
-static void
-followNecessaryForwardingInMethod(sqInt methodObj)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt assoc;
-    sqInt classObj;
-    CogMethod *cogMethod;
-    sqInt header;
-    sqInt litCount;
-
-	
+sqInt
+followLiteralofMethod(sqInt offset, sqInt methodPointer)
+{
+	return longAt((methodPointer + BaseHeaderSize) + ((offset + LiteralStart) << ShiftForWord));
 }
 
 
@@ -46283,12 +46158,10 @@
     sqInt callerContextOrNil;
     char *callerFP;
     char *callerFP1;
-    sqInt extraFramesToMoveOnOverflow = 0;
     sqInt index;
     StackPage *lruOrFree;
     StackPage *newPage;
     sqInt overflowCount;
-    StackPage * overflowedPage = 0;
     char *overflowLimitAddress;
     sqInt source;
     char *theFP;
@@ -46324,9 +46197,9 @@
 
 	GIV(statStackOverflow) += 1;
 	theFP = GIV(framePointer);
-	if (GIV(stackPage) == overflowedPage) {
+	if (GIV(stackPage) == GIV(overflowedPage)) {
 		overflowLimitAddress = ((GIV(stackPage)->baseAddress)) - GIV(overflowLimit);
-		overflowCount = (extraFramesToMoveOnOverflow += 1);
+		overflowCount = (GIV(extraFramesToMoveOnOverflow) += 1);
 		while ((((overflowCount -= 1)) >= 0)
 		 && ((((callerFP = frameCallerFP(theFP))) < overflowLimitAddress)
 		 && (!((longAt(callerFP + FoxSavedFP)) == 0)))) {
@@ -46334,8 +46207,8 @@
 		}
 	}
 	else {
-		overflowedPage = GIV(stackPage);
-		extraFramesToMoveOnOverflow = 0;
+		GIV(overflowedPage) = GIV(stackPage);
+		GIV(extraFramesToMoveOnOverflow) = 0;
 	}
 	/* begin ensureCallerContext: */
 	/* begin frameCallerFP: */
@@ -47289,7 +47162,7 @@
 			index = 0;
 			while (index <= mask) {
 				nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-				/* begin followMaybeForwardedSelector:into: */
+				
 				if (nextSelector == GIV(messageSelector)) {
 					methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 					GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -47316,7 +47189,7 @@
 				found = 0;
 				goto l1;
 			}
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -47383,7 +47256,7 @@
 		index = 0;
 		while (index <= mask) {
 			nextSelector = longAt((dictionary + BaseHeaderSize) + ((index + SelectorStart) << ShiftForWord));
-			/* begin followMaybeForwardedSelector:into: */
+			
 			if (nextSelector == GIV(messageSelector)) {
 				methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 				GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + (index << ShiftForWord));
@@ -47407,7 +47280,7 @@
 		if (nextSelector == GIV(nilObj)) {
 			return 0;
 		}
-		/* begin followMaybeForwardedSelector:into: */
+		
 		if (nextSelector == GIV(messageSelector)) {
 			methodArray = longAt((dictionary + BaseHeaderSize) + (MethodArrayIndex << ShiftForWord));
 			GIV(newMethod) = longAt((methodArray + BaseHeaderSize) + ((index - SelectorStart) << ShiftForWord));
@@ -48038,6 +47911,13 @@

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list