[Vm-dev] [commit][3738] CogVM source as per VMMaker.oscog-eem.1883

commits at squeakvm.org commits at squeakvm.org
Tue Jun 7 03:03:11 UTC 2016


Revision: 3738
Author:   eliot
Date:     2016-06-06 20:03:08 -0700 (Mon, 06 Jun 2016)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.1883

On Spur, handle external primitive failures answering PrimErrNoMemory by doing
a scavenge and retrying and then on subsequent PrimErrNoMemory failure a full
GC and then retrying.  Rename maybeRetryFailureDueToForwarding to
maybeRetryPrimitiveOnFailure.

In the Cogit, change the retry mechanism so that the primitive call is made in
the run-time, instead of the run-time answering whether the primitive should
be retried and returning to machine code that then retries.

Discussion:
First, this mechanism applies only to external (plugin) primitives.  Spur's core
primtives are written in the expectation that image-level primitive failure code
will deal with the failure and retry.  This corresponds to the VisualWorks style
and allows the image to implement GC policy (e.g. to favour reclamation over
growth).  So with the current Spur code, heavily influenced by the author's
experience with VisualWorks, it would be inapproprate to retry core primitives
on being out-of-memory.  The pathology is that attempts at very large
allocations which will inevitably fail will cause a GC in the VM, very possibly
followed by a GC from the image level primitive failure code.  Whereas leaving
it to the image, the image code may be intellkigent enough to spot an allocation
too large to ever succeed and avoid the GC altogether.

I'm not sure if I like this auto-retry or not.  Perhaps it is a good idea and
the image-level primitive failure code should be changed; there would certainly
be fewer image-level methods.  But that means fewer hooks for the image to
implement GC policy.  retryPrimitiveOnFailure which manages the retry isn't
exactly simple.

Slang:
Fix a bad bug in type inferrence as exemplified by primitiveTimesTwoPower and
its arg temporary.  A variable cannot be typed in the current pass if it is
first assigned the result of an as-yet-to-be-typed send.  If it is assigned the
result of a subsequent send then the first assignment will be ignored, possibly
leading to a badly inferred type.  For example in primitiveTimesTwoPower arg is
assigned a few times:
	arg := self stackTop.
...
	arg := objectMemory integerValueOf: arg.
...
	arg := twiceMaxExponent negated
...
	arg := twiceMaxExponent
and the type of twiceMaxExponent is #int.  If arg's type is inferred from
twiceMaxExponent because stackTop & integerValueOf: are as yet untyped, then it
will be inferred to be #int.  Whereas it should be defined as #sqInt from both
stackTop & integerValueOf:, since merging #int & #sqInt yields #sqInt.

Modified Paths:
--------------
    branches/Cog/nsspur64src/vm/cogit.h
    branches/Cog/nsspur64src/vm/cogitX64.c
    branches/Cog/nsspur64src/vm/cointerp.c
    branches/Cog/nsspur64src/vm/cointerp.h
    branches/Cog/nsspur64src/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/cogit.h
    branches/Cog/nsspursrc/vm/cogitARMv5.c
    branches/Cog/nsspursrc/vm/cogitIA32.c
    branches/Cog/nsspursrc/vm/cogitMIPSEL.c
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspurstack64src/vm/gcc3x-interp.c
    branches/Cog/nsspurstack64src/vm/interp.c
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/spur64src/vm/cogit.h
    branches/Cog/spur64src/vm/cogitX64.c
    branches/Cog/spur64src/vm/cointerp.c
    branches/Cog/spur64src/vm/cointerp.h
    branches/Cog/spur64src/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/cogit.h
    branches/Cog/spursistasrc/vm/cogitARMv5.c
    branches/Cog/spursistasrc/vm/cogitIA32.c
    branches/Cog/spursistasrc/vm/cogitMIPSEL.c
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/cogit.h
    branches/Cog/spursrc/vm/cogitARMv5.c
    branches/Cog/spursrc/vm/cogitIA32.c
    branches/Cog/spursrc/vm/cogitMIPSEL.c
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spurstack64src/vm/gcc3x-interp.c
    branches/Cog/spurstack64src/vm/interp.c
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.c
    branches/Cog/src/plugins/B2DPlugin/B2DPlugin.c
    branches/Cog/src/plugins/GeniePlugin/GeniePlugin.c
    branches/Cog/src/plugins/JPEGReaderPlugin/JPEGReaderPlugin.c
    branches/Cog/src/plugins/LargeIntegers/LargeIntegers.c
    branches/Cog/src/plugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c
    branches/Cog/src/plugins/UnixOSProcessPlugin/UnixOSProcessPlugin.c
    branches/Cog/src/plugins/ZipPlugin/ZipPlugin.c
    branches/Cog/src/vm/cogit.h
    branches/Cog/src/vm/cogitARMv5.c
    branches/Cog/src/vm/cogitIA32.c
    branches/Cog/src/vm/cogitMIPSEL.c
    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/nsspur64src/vm/cogit.h
===================================================================
--- branches/Cog/nsspur64src/vm/cogit.h	2016-06-06 16:47:45 UTC (rev 3737)
+++ branches/Cog/nsspur64src/vm/cogit.h	2016-06-07 03:03:08 UTC (rev 3738)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1877 uuid: 638b0433-98fd-4fdf-8b75-588d6c09081f
+	CCodeGenerator VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d
  */
 
 

Modified: branches/Cog/nsspur64src/vm/cogitX64.c
===================================================================
--- branches/Cog/nsspur64src/vm/cogitX64.c	2016-06-06 16:47:45 UTC (rev 3737)
+++ branches/Cog/nsspur64src/vm/cogitX64.c	2016-06-07 03:03:08 UTC (rev 3738)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1877 uuid: 638b0433-98fd-4fdf-8b75-588d6c09081f
+	CCodeGenerator VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.1877 uuid: 638b0433-98fd-4fdf-8b75-588d6c09081f
+	StackToRegisterMappingCogit VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1877 uuid: 638b0433-98fd-4fdf-8b75-588d6c09081f " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -441,7 +441,7 @@
 static usqInt NoDbgRegParms inlineCacheTagAt(AbstractInstruction * self_in_inlineCacheTagAt, sqInt callSiteReturnAddress);
 static sqInt NoDbgRegParms isPCDependent(AbstractInstruction * self_in_isPCDependent);
 static usqInt NoDbgRegParms literal32BeforeFollowingAddress(AbstractInstruction * self_in_literal32BeforeFollowingAddress, sqInt followingAddress);
-static sqInt NoDbgRegParms literalBeforeFollowingAddress(AbstractInstruction * self_in_literalBeforeFollowingAddress, sqInt followingAddress);
+static void NoDbgRegParms literalBeforeFollowingAddress(AbstractInstruction * self_in_literalBeforeFollowingAddress, sqInt followingAddress);
 static sqInt NoDbgRegParms loadLiteralByteSize(AbstractInstruction * self_in_loadLiteralByteSize);
 static usqInt NoDbgRegParms sizePCDependentInstructionAt(AbstractInstruction * self_in_sizePCDependentInstructionAt, sqInt eventualAbsoluteAddress);
 static AbstractInstruction * NoDbgRegParms storeLiteralbeforeFollowingAddress(AbstractInstruction * self_in_storeLiteralbeforeFollowingAddress, sqInt literal, sqInt followingAddress);
@@ -602,7 +602,7 @@
 static AbstractInstruction * NoDbgRegParms gMoveCwR(sqInt wordConstant, sqInt reg);
 static AbstractInstruction * NoDbgRegParms gMoveRMwr(sqInt sourceReg, sqInt offset, sqInt baseReg);
 static AbstractInstruction * NoDbgRegParms gMoveRR(sqInt reg1, sqInt reg2);
-static sqInt NoDbgRegParms mapEndFor(CogMethod *cogMethod);
+static usqInt NoDbgRegParms mapEndFor(CogMethod *cogMethod);
 static sqInt NoDbgRegParms mapForperformUntilarg(CogMethod *cogMethod, sqInt (*functionSymbol)(sqInt annotation, char *mcpc, sqInt arg), sqInt arg);
 static sqInt NoDbgRegParms mapObjectReferencesInClosedPIC(CogMethod *cPIC);
 static void mapObjectReferencesInGeneratedRuntime(void);
@@ -878,7 +878,7 @@
 static void NoDbgRegParms markAndTraceLiteralinat(sqInt literal, CogMethod *cogMethod, sqInt *address);
 static void NoDbgRegParms markAndTraceUpdatedLiteralin(sqInt objOop, CogMethod *cogMethodOrNil);
 static void NoDbgRegParms markIfIRC(usqInt maybeIRCs);
-static sqInt NoDbgRegParms maybeCompileRetryonPrimitiveFail(AbstractInstruction *retryInst, sqInt primIndex);
+static sqInt NoDbgRegParms maybeCompileRetryOnPrimitiveFail(sqInt primIndex);
 static sqInt numCharacterBits(void);
 extern sqInt numRegArgs(void);
 static sqInt NoDbgRegParms remapObject(sqInt objOop);
@@ -892,7 +892,7 @@
 static SimStackEntry * NoDbgRegParms storeToReg(SimStackEntry * self_in_storeToReg, sqInt reg);
 static sqInt NoDbgRegParms isMergeFixup(BytecodeFixup * self_in_isMergeFixup);
 static sqInt NoDbgRegParms availableRegisterOrNoneFor(AbstractInstruction * self_in_availableRegisterOrNoneFor, sqInt liveRegsMask);
-static sqInt NoDbgRegParms callFullTargetFromReturnAddress(AbstractInstruction * self_in_callFullTargetFromReturnAddress, sqInt callSiteReturnAddress);
+static void NoDbgRegParms callFullTargetFromReturnAddress(AbstractInstruction * self_in_callFullTargetFromReturnAddress, sqInt callSiteReturnAddress);
 static sqInt NoDbgRegParms callInstructionByteSize(AbstractInstruction * self_in_callInstructionByteSize);
 static sqInt NoDbgRegParms callTargetFromReturnAddress(AbstractInstruction * self_in_callTargetFromReturnAddress, sqInt callSiteReturnAddress);
 static sqInt NoDbgRegParms cmpC32RTempByteSize(AbstractInstruction * self_in_cmpC32RTempByteSize);
@@ -939,7 +939,7 @@
 static usqInt NoDbgRegParms machineCodeAt(AbstractInstruction * self_in_machineCodeAt, sqInt anOffset);
 static sqInt NoDbgRegParms machineCodeBytes(AbstractInstruction * self_in_machineCodeBytes);
 static sqInt NoDbgRegParms modRMRO(AbstractInstruction * self_in_modRMRO, sqInt mod, sqInt regMode, sqInt regOpcode);
-static sqInt NoDbgRegParms nsSendCacheAt(AbstractInstruction * self_in_nsSendCacheAt, char *callSiteReturnAddress);
+static void NoDbgRegParms nsSendCacheAt(AbstractInstruction * self_in_nsSendCacheAt, char *callSiteReturnAddress);
 static sqInt NoDbgRegParms numIntRegArgs(AbstractInstruction * self_in_numIntRegArgs);
 static AbstractInstruction * NoDbgRegParms padIfPossibleWithStopsFromto(AbstractInstruction * self_in_padIfPossibleWithStopsFromto, sqInt startAddr, sqInt endAddr);
 static AbstractInstruction * NoDbgRegParms relocateCallBeforeReturnPCby(AbstractInstruction * self_in_relocateCallBeforeReturnPCby, sqInt retpc, sqInt delta);
@@ -2360,7 +2360,7 @@
 	least 16rC0. */
 
 	/* CogInLineLiteralsX64Compiler>>#literalBeforeFollowingAddress: */
-static sqInt NoDbgRegParms
+static void NoDbgRegParms
 literalBeforeFollowingAddress(AbstractInstruction * self_in_literalBeforeFollowingAddress, sqInt followingAddress)
 {
     sqInt base;
@@ -2374,7 +2374,8 @@
 			? 9
 			: 10)
 	: 11));
-	return unalignedLongAt(base);
+	unalignedLongAt(base);
+	return;
 }
 
 	/* CogInLineLiteralsX64Compiler>>#loadLiteralByteSize */
@@ -2798,12 +2799,12 @@
     sqInt byte;
     BytecodeDescriptor *descriptor;
     sqInt distance;
-    usqInt endbcpc;
+    sqInt endbcpc;
     CogMethod *homeMethod;
     sqInt isBackwardBranch;
     sqInt isInBlock;
     sqInt latestContinuation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
     usqInt mcpc1;
     sqInt nExts;
@@ -4407,12 +4408,11 @@
     AbstractInstruction *anInstruction7;
     sqInt callTarget;
     const int cStackAlignment = STACK_ALIGN_BYTES;
-    usqInt delta;
-    usqInt numRegsPushed;
-    sqInt quickConstant;
+    sqInt delta;
+    sqInt numRegsPushed;
     usqInt regMaskCopy;
     sqInt regsToSave;
-    usqInt wordsPushedModAlignment;
+    sqInt wordsPushedModAlignment;
 
 	regsToSave = (resultRegOrNone == NoReg
 		? regMask
@@ -4433,9 +4433,7 @@
 		if (wordsPushedModAlignment != 0) {
 			delta = (cStackAlignment / BytesPerWord) - wordsPushedModAlignment;
 			/* begin SubCq:R: */
-			quickConstant = delta * BytesPerWord;
-			/* begin gen:quickConstant:operand: */
-			anInstruction = genoperandoperand(SubCqR, quickConstant, SPReg);
+			anInstruction = genoperandoperand(SubCqR, delta * BytesPerWord, SPReg);
 		}
 	l1:	/* end genAlignCStackSavingRegisters:numArgs:wordAlignment: */;
 	}
@@ -5362,9 +5360,9 @@
 followForwardedLiteralsIn(CogMethod *cogMethod)
 {
     sqInt annotation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	assert((((cogMethod->cmType)) != CMMethod)
@@ -7177,10 +7175,10 @@
 /*	Answer the address of the null byte at the end of the method map. */
 
 	/* Cogit>>#mapEndFor: */
-static sqInt NoDbgRegParms
+static usqInt NoDbgRegParms
 mapEndFor(CogMethod *cogMethod)
 {
-    sqInt end;
+    usqInt end;
 
 	end = ((((usqInt)cogMethod)) + ((cogMethod->blockSize))) - 1;
 	while ((byteAt(end)) != MapEnd) {
@@ -7198,9 +7196,9 @@
 mapForperformUntilarg(CogMethod *cogMethod, sqInt (*functionSymbol)(sqInt annotation, char *mcpc, sqInt arg), sqInt arg)
 {
     sqInt annotation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	mcpc = (0
@@ -7305,9 +7303,9 @@
     sqInt freedPIC;
     sqInt hasYoungObj;
     sqInt hasYoungObjPtr;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt remappedMethod;
     sqInt result;
     sqInt val;
@@ -7423,9 +7421,9 @@
 {
     sqInt annotation;
     CogMethod *cogMethod;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	codeModified = 0;
@@ -7503,9 +7501,9 @@
     CogMethod *cogMethod;
     sqInt hasYoungObj;
     sqInt hasYoungObjPtr;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     usqInt pointer;
     sqInt result;
     sqInt val;
@@ -7623,12 +7621,12 @@
     sqInt annotation;
     sqInt annotation1;
     CogMethod *cogMethod;
-    sqInt map;
-    sqInt map1;
+    usqInt map;
+    usqInt map1;
     sqInt mapByte;
     sqInt mapByte1;
-    sqInt mcpc;
-    sqInt mcpc1;
+    usqInt mcpc;
+    usqInt mcpc1;
     sqInt result;
     sqInt result1;
     sqInt val;
@@ -7783,9 +7781,9 @@
 markAndTraceOrFreeCogMethodfirstVisit(CogMethod *cogMethod, sqInt firstVisit)
 {
     sqInt annotation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
     sqInt val;
 
@@ -8111,9 +8109,9 @@
 {
     sqInt annotation;
     CogMethod *cogMethod;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	assert((((aCogMethod->cmType)) == CMMethod)
@@ -8239,12 +8237,12 @@
     sqInt byte;
     BytecodeDescriptor *descriptor;
     sqInt distance;
-    usqInt endbcpc;
+    sqInt endbcpc;
     CogMethod *homeMethod;
     sqInt isBackwardBranch;
     sqInt isInBlock;
     sqInt latestContinuation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
     usqInt mcpc;
     sqInt nExts;
@@ -8868,9 +8866,9 @@
 {
     sqInt annotation;
     sqLong callDelta;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqLong refDelta;
     sqInt result;
 
@@ -9442,9 +9440,9 @@
 {
     sqInt annotation;
     CogMethod *cogMethod;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	if (!(methodZoneBase)) {
@@ -9885,9 +9883,9 @@
     sqInt annotation;
     CogMethod *cogMethod;
     sqInt freedPIC;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	if (!(methodZoneBase)) {
@@ -9962,9 +9960,9 @@
 {
     sqInt annotation;
     CogMethod *cogMethod;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt mustScanAndUnlink;
     sqInt result;
 
@@ -10061,9 +10059,9 @@
 {
     sqInt annotation;
     CogMethod *cogMethod;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
 
 	if (!(methodZoneBase)) {
@@ -10130,9 +10128,9 @@
     sqInt annotation;
     CogMethod *cogMethod;
     sqInt freedPIC;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
-    sqInt mcpc;
+    usqInt mcpc;
     sqInt result;
     CogMethod *targetMethod;
 
@@ -16545,36 +16543,47 @@
 }
 
 
-/*	If primIndex has an accessorDepth, check for primitive failure and call
-	ceCheckForAndFollowForwardedPrimitiveState if so If ceCheck.... answers
-	true, retry the primitive. */
+/*	If primIndex has an accessorDepth and fails, or it is external and fails
+	with PrimErrNoMemory,
+	call ceCheckAndMaybeRetryPrimitive if so If ceCheck.... answers true,
+	retry the primitive. */
 
-	/* CogObjectRepresentationForSpur>>#maybeCompileRetry:onPrimitiveFail: */
+	/* CogObjectRepresentationForSpur>>#maybeCompileRetryOnPrimitiveFail: */
 static sqInt NoDbgRegParms
-maybeCompileRetryonPrimitiveFail(AbstractInstruction *retryInst, sqInt primIndex)
+maybeCompileRetryOnPrimitiveFail(sqInt primIndex)
 {
     sqInt address;
+    sqInt address1;
     AbstractInstruction *anInstruction;
     AbstractInstruction *anInstruction1;
     AbstractInstruction *anInstruction2;
+    AbstractInstruction *anInstruction3;
     AbstractInstruction *jmp;
 
-	if ((accessorDepthForPrimitiveIndex(primIndex)) < 0) {
-		return 0;
+	if ((accessorDepthForPrimitiveIndex(primIndex)) >= 0) {
+		/* begin MoveAw:R: */
+		address = primFailCodeAddress();
+		/* begin gen:literal:operand: */
+		anInstruction = genoperandoperand(MoveAwR, address, TempReg);
+		/* begin CmpCq:R: */
+		anInstruction1 = genoperandoperand(CmpCqR, 0, TempReg);
+		/* begin JumpZero: */
+		jmp = genConditionalBranchoperand(JumpZero, ((sqInt)0));
 	}
-	/* begin MoveAw:R: */
-	address = primFailCodeAddress();
-	/* begin gen:literal:operand: */
-	anInstruction = genoperandoperand(MoveAwR, address, TempReg);
-	/* begin CmpCq:R: */
-	anInstruction1 = genoperandoperand(CmpCqR, 0, TempReg);
-	/* begin JumpZero: */
-	jmp = genConditionalBranchoperand(JumpZero, ((sqInt)0));
-	compileCallFornumArgsargargargargresultRegregsToSave(ceCheckForAndFollowForwardedPrimitiveState, 0, null, null, null, null, TempReg, 0);
-	/* begin CmpCq:R: */
-	anInstruction2 = genoperandoperand(CmpCqR, 0, TempReg);
-	/* begin JumpNonZero: */
-	genConditionalBranchoperand(JumpNonZero, ((sqInt)retryInst));
+	else {
+		if ((primNumberExternalCall()) != primIndex) {
+			return 0;
+		}
+		/* begin MoveAw:R: */
+		address1 = primFailCodeAddress();
+		/* begin gen:literal:operand: */
+		anInstruction2 = genoperandoperand(MoveAwR, address1, TempReg);
+		/* begin CmpCq:R: */
+		anInstruction3 = genoperandoperand(CmpCqR, PrimErrNoMemory, TempReg);
+		/* begin JumpNonZero: */
+		jmp = genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
+	}
+	compileCallFornumArgsargargargargresultRegregsToSave(ceCheckAndMaybeRetryPrimitive, 1, trampolineArgConstant(primIndex), null, null, null, TempReg, 0);
 	jmpTarget(jmp, gLabel());
 	return 0;
 }
@@ -16898,10 +16907,12 @@
  */
 
 	/* CogX64Compiler>>#callFullTargetFromReturnAddress: */
-static sqInt NoDbgRegParms
+static void NoDbgRegParms
 callFullTargetFromReturnAddress(AbstractInstruction * self_in_callFullTargetFromReturnAddress, sqInt callSiteReturnAddress)
 {
-	return unalignedLongAt((callSiteReturnAddress - 2) - 8);
+	/* begin sixtyFourBitLiteralBefore: */
+	unalignedLongAt((callSiteReturnAddress - 2) - 8);
+	return;
 }
 
 	/* CogX64Compiler>>#callInstructionByteSize */
@@ -20947,10 +20958,11 @@
 	self, super, outer, or implicit receiver send. */
 
 	/* CogX64Compiler>>#nsSendCacheAt: */
-static sqInt NoDbgRegParms
+static void NoDbgRegParms
 nsSendCacheAt(AbstractInstruction * self_in_nsSendCacheAt, char *callSiteReturnAddress)
 {
-	return literalBeforeFollowingAddress(self_in_nsSendCacheAt, (((usqInt)callSiteReturnAddress)) - 5);
+	literalBeforeFollowingAddress(self_in_nsSendCacheAt, (((usqInt)callSiteReturnAddress)) - 5);
+	return;
 }
 
 	/* CogX64Compiler>>#numIntRegArgs */
@@ -21471,7 +21483,6 @@
     sqInt offset2;
     sqInt reg;
     sqInt retpc;
-    AbstractInstruction *retry;
 
 
 	/* Save processor fp, sp and return pc in the interpreter's frame stack and instruction pointers */
@@ -21501,7 +21512,6 @@
 	}
 	/* begin MoveCq:R: */
 	anInstruction21 = genoperandoperand(MoveCqR, 0, TempReg);
-	retry = anInstruction21;
 	/* begin MoveR:Aw: */
 	address11 = primFailCodeAddress();
 	/* begin gen:operand:literal: */
@@ -21585,7 +21595,7 @@
 			/* begin Label */
 			continuePostSamplePrim = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
 		}
-		maybeCompileRetryonPrimitiveFail(retry, primitiveIndex);
+		maybeCompileRetryOnPrimitiveFail(primitiveIndex);
 		maybeCompileAllocFillerCheck();
 		/* begin MoveAw:R: */
 		address8 = instructionPointerAddress();
@@ -23159,13 +23169,13 @@
     CogBlockMethod *cogMethod1;
     BytecodeDescriptor *descriptor;
     sqInt distance;
-    usqInt endbcpc;
+    sqInt endbcpc;
     sqInt errCode;
     CogMethod *homeMethod;
     sqInt isBackwardBranch;
     sqInt isInBlock;
     sqInt latestContinuation;
-    sqInt map;
+    usqInt map;
     sqInt mapByte;
     usqInt mcpc;
     sqInt nExts;

Modified: branches/Cog/nsspur64src/vm/cointerp.c
===================================================================
--- branches/Cog/nsspur64src/vm/cointerp.c	2016-06-06 16:47:45 UTC (rev 3737)
+++ branches/Cog/nsspur64src/vm/cointerp.c	2016-06-07 03:03:08 UTC (rev 3738)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1876 uuid: 28e91d90-4197-436d-9702-7c7dae02e85e
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d
    from
-	CoInterpreter VMMaker.oscog-eem.1876 uuid: 28e91d90-4197-436d-9702-7c7dae02e85e
+	CoInterpreter VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1876 uuid: 28e91d90-4197-436d-9702-7c7dae02e85e " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1883 uuid: a87f979f-7e5b-44d1-804d-fc8403bde06d " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -447,7 +447,7 @@
 extern sqInt ceCannotAssignTowithIndexvalueToAssign(sqInt immutableObject, sqInt index, sqInt valueToAssign);
 #endif /* IMMUTABILITY */
 extern sqInt ceCannotResume(void);
-extern sqInt ceCheckForAndFollowForwardedPrimitiveState(void);
+extern void ceCheckAndMaybeRetryPrimitive(sqInt primIndex);
 extern void ceCheckForInterrupts(void);
 extern void ceCheckProfileTick(void);
 extern sqInt ceContextinstVar(sqInt maybeContext, sqInt slotIndex);
@@ -471,7 +471,6 @@
 extern void ceTraceStoreOfinto(sqInt aValue, sqInt anObject);
 extern void checkAssertsEnabledInCoInterpreter(void);
 static sqInt NoDbgRegParms checkCodeIntegrity(sqInt gcModes);
-static sqInt checkForAndFollowForwardedPrimitiveState(void);
 static sqInt checkLogIntegrity(void);
 static sqInt NoDbgRegParms checkOkayFields(sqInt oop);
 static sqInt checkStackIntegrity(void);
@@ -1254,7 +1253,7 @@
 extern void tenuringIncrementalGC(void);
 static sqInt NoDbgRegParms topOfObjStack(sqInt objStack);
 extern sqInt topRemappableOop(void);
-static usqInt totalFreeListBytes(void);
+static sqInt totalFreeListBytes(void);
 extern sqInt trueObject(void);
 static void NoDbgRegParms unlinkSolitaryFreeTreeNode(sqInt freeTreeNode);
 extern sqInt unpinObject(sqInt objOop);
@@ -1517,6 +1516,7 @@
 extern sqInt readableFormat(sqInt imageVersion);
 EXPORT(sqInt) reestablishContextPriorToCallback(sqInt callbackContext);
 static sqInt NoDbgRegParms removeFirstLinkOfList(sqInt aList);
+static sqInt retryPrimitiveOnFailure(void);
 EXPORT(sqInt) returnAsThroughCallbackContext(sqInt returnTypeOop, VMCallbackContext *vmCallbackContext, sqInt callbackMethodContext);
 static sqInt NoDbgRegParms reverseDisplayFromto(sqInt startIndex, sqInt endIndex);
 static sqInt NoDbgRegParms safeMethodClassOf(sqInt methodPointer);
@@ -1651,10 +1651,10 @@
 _iss sqInt classTableFirstPage;
 _iss sqInt traceLogIndex;
 _iss sqInt * freeLists;
+_iss unsigned char primTraceLogIndex;
 _iss usqInt scavengeThreshold;
 _iss char * stackLimit;
 _iss sqInt lkupClass;
-_iss unsigned char primTraceLogIndex;
 _iss sqInt rememberedSetSize;
 _iss sqInt * rememberedSet;
 _iss sqInt localAbsentReceiverOrZero;
@@ -2452,7 +2452,7 @@
 	};
 sqInt checkedPluginName;
 char expensiveAsserts = 0;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1876";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1883";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -2486,6 +2486,7 @@
 		compilationBreakpointFor(sel); \
 	} \
 } while (0)
+#define primNumberExternalCall() 117
 #define primTraceLogIndex(aValue) (GIV(primTraceLogIndex) = (aValue))
 #define setDesiredCogCodeSize(dccs) (desiredCogCodeSize = (dccs))
 #define pageIndexForstackBasePlus1bytesPerPage(pointer,stkBasePlus1,pageByteSize) (((char *)(pointer) - (stkBasePlus1)) / (pageByteSize))
@@ -5959,12 +5960,9 @@
 						GIV(primFailCode) = 0;
 						dispatchFunctionPointer(primitiveFunctionPointer);
 						assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-						/* begin maybeRetryFailureDueToForwarding */
-						if (GIV(primFailCode)
-						 && (checkForAndFollowForwardedPrimitiveState())) {
-							/* begin initPrimCall */
-							GIV(primFailCode) = 0;
-							dispatchFunctionPointer(primitiveFunctionPointer);
+						/* begin maybeRetryPrimitiveOnFailure */
+						if (GIV(primFailCode)) {
+							retryPrimitiveOnFailure();
 						}
 						/* begin maybeFailForLastObjectOverwrite */
 						if (checkAllocFiller) {
@@ -6074,11 +6072,11 @@
 										table = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (((long)PrimErrTableIndex) << (shiftForWord())));
 										if (GIV(primFailCode) <= (numSlotsOf(table))) {
 											errorCode = longAt((table + BaseHeaderSize) + (((long)(GIV(primFailCode) - 1)) << (shiftForWord())));
-											goto l446;
+											goto l442;
 										}
 									}
 									errorCode = ((GIV(primFailCode) << 3) | 1);
-								l446:	/* end getErrorObjectFromPrimFailCode */;
+								l442:	/* end getErrorObjectFromPrimFailCode */;
 									longAtPointerput(localSP, errorCode);
 								}
 								GIV(primFailCode) = 0;
@@ -12929,25 +12927,25 @@
 						if (localPrimIndex >= 264) {
 							/* begin internalStackTopPut: */
 							longAtPointerput(localSP, longAt(((longAtPointer(localSP)) + BaseHeaderSize) + (((long)(localPrimIndex - 264)) << (shiftForWord()))));
-							goto l463;
+							goto l474;
 						}
 						if (localPrimIndex == 256) {
-							goto l463;
+							goto l474;
 						}
 						if (localPrimIndex == 257) {
 							longAtPointerput(localSP, GIV(trueObj));
-							goto l463;
+							goto l474;
 						}
 						if (localPrimIndex == 258) {
 							longAtPointerput(localSP, GIV(falseObj));
-							goto l463;
+							goto l474;
 						}
 						if (localPrimIndex == 259) {
 							longAtPointerput(localSP, GIV(nilObj));
-							goto l463;
+							goto l474;
 						}
 						longAtPointerput(localSP, (((localPrimIndex - 261) << 3) | 1));
-					l463:	/* end internalQuickPrimitiveResponse */;
+					l474:	/* end internalQuickPrimitiveResponse */;
 						goto l464;
 					}
 					/* begin externalizeIPandSP */
@@ -12971,12 +12969,9 @@
 					GIV(primFailCode) = 0;
 					dispatchFunctionPointer(primitiveFunctionPointer);
 					assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-					/* begin maybeRetryFailureDueToForwarding */
-					if (GIV(primFailCode)
-					 && (checkForAndFollowForwardedPrimitiveState())) {
-						/* begin initPrimCall */
-						GIV(primFailCode) = 0;
-						dispatchFunctionPointer(primitiveFunctionPointer);
+					/* begin maybeRetryPrimitiveOnFailure */
+					if (GIV(primFailCode)) {
+						retryPrimitiveOnFailure();
 					}
 					/* begin maybeFailForLastObjectOverwrite */
 					if (checkAllocFiller) {
@@ -13086,11 +13081,11 @@
 									table = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (((long)PrimErrTableIndex) << (shiftForWord())));
 									if (GIV(primFailCode) <= (numSlotsOf(table))) {
 										errorCode = longAt((table + BaseHeaderSize) + (((long)(GIV(primFailCode) - 1)) << (shiftForWord())));
-										goto l475;
+										goto l469;
 									}
 								}
 								errorCode = ((GIV(primFailCode) << 3) | 1);
-							l475:	/* end getErrorObjectFromPrimFailCode */;
+							l469:	/* end getErrorObjectFromPrimFailCode */;
 								longAtPointerput(localSP, errorCode);
 							}
 							GIV(primFailCode) = 0;
@@ -13292,25 +13287,25 @@
 						if (localPrimIndex >= 264) {
 							/* begin internalStackTopPut: */
 							longAtPointerput(localSP, longAt(((longAtPointer(localSP)) + BaseHeaderSize) + (((long)(localPrimIndex - 264)) << (shiftForWord()))));
-							goto l480;
+							goto l486;
 						}
 						if (localPrimIndex == 256) {
-							goto l480;
+							goto l486;
 						}
 						if (localPrimIndex == 257) {
 							longAtPointerput(localSP, GIV(trueObj));
-							goto l480;
+							goto l486;
 						}
 						if (localPrimIndex == 258) {
 							longAtPointerput(localSP, GIV(falseObj));
-							goto l480;
+							goto l486;
 						}
 						if (localPrimIndex == 259) {
 							longAtPointerput(localSP, GIV(nilObj));
-							goto l480;
+							goto l486;
 						}
 						longAtPointerput(localSP, (((localPrimIndex - 261) << 3) | 1));
-					l480:	/* end internalQuickPrimitiveResponse */;
+					l486:	/* end internalQuickPrimitiveResponse */;
 						goto l481;
 					}
 					/* begin externalizeIPandSP */
@@ -13334,12 +13329,9 @@
 					GIV(primFailCode) = 0;
 					dispatchFunctionPointer(primitiveFunctionPointer);
 					assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-					/* begin maybeRetryFailureDueToForwarding */
-					if (GIV(primFailCode)
-					 && (checkForAndFollowForwardedPrimitiveState())) {
-						/* begin initPrimCall */
-						GIV(primFailCode) = 0;
-						dispatchFunctionPointer(primitiveFunctionPointer);
+					/* begin maybeRetryPrimitiveOnFailure */
+					if (GIV(primFailCode)) {
+						retryPrimitiveOnFailure();
 					}
 					/* begin maybeFailForLastObjectOverwrite */
 					if (checkAllocFiller) {
@@ -13449,11 +13441,11 @@
 									table = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (((long)PrimErrTableIndex) << (shiftForWord())));
 									if (GIV(primFailCode) <= (numSlotsOf(table))) {
 										errorCode = longAt((table + BaseHeaderSize) + (((long)(GIV(primFailCode) - 1)) << (shiftForWord())));
-										goto l487;
+										goto l484;
 									}
 								}
 								errorCode = ((GIV(primFailCode) << 3) | 1);
-							l487:	/* end getErrorObjectFromPrimFailCode */;
+							l484:	/* end getErrorObjectFromPrimFailCode */;
 								longAtPointerput(localSP, errorCode);
 							}
 							GIV(primFailCode) = 0;
@@ -13761,25 +13753,25 @@
 						if (localPrimIndex >= 264) {
 							/* begin internalStackTopPut: */
 							longAtPointerput(localSP, longAt(((longAtPointer(localSP)) + BaseHeaderSize) + (((long)(localPrimIndex - 264)) << (shiftForWord()))));
-							goto l374;
+							goto l380;
 						}
 						if (localPrimIndex == 256) {
-							goto l374;
+							goto l380;
 						}
 						if (localPrimIndex == 257) {
 							longAtPointerput(localSP, GIV(trueObj));
-							goto l374;
+							goto l380;
 						}
 						if (localPrimIndex == 258) {
 							longAtPointerput(localSP, GIV(falseObj));
-							goto l374;
+							goto l380;
 						}
 						if (localPrimIndex == 259) {
 							longAtPointerput(localSP, GIV(nilObj));
-							goto l374;
+							goto l380;
 						}
 						longAtPointerput(localSP, (((localPrimIndex - 261) << 3) | 1));
-					l374:	/* end internalQuickPrimitiveResponse */;
+					l380:	/* end internalQuickPrimitiveResponse */;
 						goto l382;
 					}
 					/* begin externalizeIPandSP */
@@ -13803,12 +13795,9 @@
 					GIV(primFailCode) = 0;
 					dispatchFunctionPointer(primitiveFunctionPointer);
 					assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-					/* begin maybeRetryFailureDueToForwarding */
-					if (GIV(primFailCode)
-					 && (checkForAndFollowForwardedPrimitiveState())) {
-						/* begin initPrimCall */
-						GIV(primFailCode) = 0;
-						dispatchFunctionPointer(primitiveFunctionPointer);
+					/* begin maybeRetryPrimitiveOnFailure */
+					if (GIV(primFailCode)) {
+						retryPrimitiveOnFailure();
 					}
 					/* begin maybeFailForLastObjectOverwrite */
 					if (checkAllocFiller) {
@@ -13918,11 +13907,11 @@
 									table = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (((long)PrimErrTableIndex) << (shiftForWord())));
 									if (GIV(primFailCode) <= (numSlotsOf(table))) {
 										errorCode = longAt((table + BaseHeaderSize) + (((long)(GIV(primFailCode) - 1)) << (shiftForWord())));
-										goto l381;
+										goto l378;
 									}
 								}
 								errorCode = ((GIV(primFailCode) << 3) | 1);
-							l381:	/* end getErrorObjectFromPrimFailCode */;
+							l378:	/* end getErrorObjectFromPrimFailCode */;
 								longAtPointerput(localSP, errorCode);
 							}
 							GIV(primFailCode) = 0;
@@ -14232,25 +14221,25 @@
 						if (localPrimIndex >= 264) {
 							/* begin internalStackTopPut: */
 							longAtPointerput(localSP, longAt(((longAtPointer(localSP)) + BaseHeaderSize) + (((long)(localPrimIndex - 264)) << (shiftForWord()))));
-							goto l399;
+							goto l405;
 						}
 						if (localPrimIndex == 256) {
-							goto l399;
+							goto l405;
 						}
 						if (localPrimIndex == 257) {
 							longAtPointerput(localSP, GIV(trueObj));
-							goto l399;
+							goto l405;
 						}
 						if (localPrimIndex == 258) {
 							longAtPointerput(localSP, GIV(falseObj));
-							goto l399;
+							goto l405;
 						}
 						if (localPrimIndex == 259) {
 							longAtPointerput(localSP, GIV(nilObj));
-							goto l399;
+							goto l405;
 						}
 						longAtPointerput(localSP, (((localPrimIndex - 261) << 3) | 1));
-					l399:	/* end internalQuickPrimitiveResponse */;
+					l405:	/* end internalQuickPrimitiveResponse */;
 						goto l407;
 					}
 					/* begin externalizeIPandSP */
@@ -14274,12 +14263,9 @@
 					GIV(primFailCode) = 0;
 					dispatchFunctionPointer(primitiveFunctionPointer);
 					assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-					/* begin maybeRetryFailureDueToForwarding */
-					if (GIV(primFailCode)
-					 && (checkForAndFollowForwardedPrimitiveState())) {
-						/* begin initPrimCall */
-						GIV(primFailCode) = 0;
-						dispatchFunctionPointer(primitiveFunctionPointer);
+					/* begin maybeRetryPrimitiveOnFailure */
+					if (GIV(primFailCode)) {
+						retryPrimitiveOnFailure();
 					}
 					/* begin maybeFailForLastObjectOverwrite */
 					if (checkAllocFiller) {
@@ -14389,11 +14375,11 @@
 									table = longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (((long)PrimErrTableIndex) << (shiftForWord())));
 									if (GIV(primFailCode) <= (numSlotsOf(table))) {
 										errorCode = longAt((table + BaseHeaderSize) + (((long)(GIV(primFailCode) - 1)) << (shiftForWord())));
-										goto l406;
+										goto l403;
 									}
 								}
 								errorCode = ((GIV(primFailCode) << 3) | 1);
-							l406:	/* end getErrorObjectFromPrimFailCode */;
+							l403:	/* end getErrorObjectFromPrimFailCode */;
 								longAtPointerput(localSP, errorCode);
 							}
 							GIV(primFailCode) = 0;
@@ -15477,19 +15463,16 @@
 
 	assert(GIV(primFailCode) != 0);
 	assert(GIV(newMethod) == aPrimitiveMethod);
-	if (checkForAndFollowForwardedPrimitiveState()) {
-		/* begin initPrimCall */
-		GIV(primFailCode) = 0;
-		dispatchFunctionPointer(primitiveFunctionPointer);
-		if (!GIV(primFailCode)) {
-			result = longAt(GIV(stackPointer));
-			longAtPointerput(GIV(stackPointer), GIV(instructionPointer));
-			/* begin push: */
-			longAtput((sp = GIV(stackPointer) - BytesPerWord), result);
-			GIV(stackPointer) = sp;
-			ceEnterCogCodePopReceiverReg();
-		}
+	retryPrimitiveOnFailure();
+	if (!GIV(primFailCode)) {
+		result = longAt(GIV(stackPointer));
+		longAtPointerput(GIV(stackPointer), GIV(instructionPointer));
+		/* begin push: */
+		longAtput((sp = GIV(stackPointer) - BytesPerWord), result);
+		GIV(stackPointer) = sp;
+		ceEnterCogCodePopReceiverReg();
 	}
+
 	methodHeader = longAt((aPrimitiveMethod + BaseHeaderSize) + (((long)HeaderIndex) << (shiftForWord())));
 	if (isCogMethodReference(methodHeader)) {
 		activateCoggedNewMethod(0);
@@ -15718,16 +15701,28 @@
 }
 
 
-/*	In Spur a primitive may fail due to encountering a forwarder.
-	On failure check the accessorDepth for the primitive and
-	if non-negative scan the args to the depth, following any
-	forwarders. Answer if any are found so the prim can be retried. */
+/*	Log failure and then retry if there's an accessorDepth or failure due to
+	no memory.
+ */
 
-	/* CoInterpreter>>#ceCheckForAndFollowForwardedPrimitiveState */
-sqInt
-ceCheckForAndFollowForwardedPrimitiveState(void)
-{
-	return checkForAndFollowForwardedPrimitiveState();
+	/* CoInterpreter>>#ceCheckAndMaybeRetryPrimitive: */
+void
+ceCheckAndMaybeRetryPrimitive(sqInt primIndex)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt retried;
+
+	if (recordPrimTrace()) {
+		/* begin fastLogPrim: */
+		GIV(primTraceLog)[GIV(primTraceLogIndex)] = TracePrimitiveFailure;
+		primTraceLogIndex(GIV(primTraceLogIndex) + 1);
+	}
+	retried = retryPrimitiveOnFailure();
+	if (retried
+	 && (recordPrimTrace())) {
+		/* begin fastLogPrim: */
+		GIV(primTraceLog)[GIV(primTraceLogIndex)] = TracePrimitiveRetry;
+		primTraceLogIndex(GIV(primTraceLogIndex) + 1);
+	}
 }
 
 	/* CoInterpreter>>#ceCheckForInterrupts */
@@ -17483,117 +17478,6 @@
 }
 
 
-/*	In Spur a primitive may fail due to encountering a forwarder. On failure,
-	check the accessorDepth for the primitive and if non-negative scan the
-	args to the depth, following any forwarders. Answer if any are found so
-	the prim can be retried. The primitive index is derived from newMethod.
-	If the primitive is 118, then primitiveDoPrimitiveWithArgs sets newMethod
-	to a SmallInteger whose value is the primitive it is evaluating. */
-/*	Override to log */
-
-	/* CoInterpreter>>#checkForAndFollowForwardedPrimitiveState */
-static sqInt
-checkForAndFollowForwardedPrimitiveState(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    signed char accessorDepth;
-    sqInt firstBytecode;
-    sqInt found;
-    sqInt found1;
-    sqInt header;
-    sqInt index;
-    sqInt methodHeader;
-    sqInt oop;
-    sqInt primIndex;
-    sqInt referent;
-    sqInt scannedStackFrame;
-
-	if (recordPrimTrace()) {
-		/* begin fastLogPrim: */
-		GIV(primTraceLog)[GIV(primTraceLogIndex)] = TracePrimitiveFailure;
-		primTraceLogIndex(GIV(primTraceLogIndex) + 1);
-	}
-	assert(failed());
-	found1 = (scannedStackFrame = 0);
-	if ((((GIV(newMethod)) & 7) == 1)) {
-		primIndex = (GIV(newMethod) >> 3);
-	}
-	else {
-		assert(GIV(argumentCount) == (argumentCountOf(GIV(newMethod))));
-		/* begin primitiveIndexOfMethod:header: */
-		assert(isCompiledMethod(GIV(newMethod)));
-		header = longAt((GIV(newMethod) + BaseHeaderSize) + (((long)HeaderIndex) << (shiftForWord())));
-		if ((((header) & 7) == 1)) {
-			methodHeader = header;
-		}
-		else {
-			assert((((usqInt)header)) < GIV(newSpaceStart));
-			assert((((((CogMethod *) header))->objectHeader)) == (nullHeaderForMachineCodeMethod()));
-			methodHeader = ((((CogMethod *) header))->methodHeader);
-		}
-		if (methodHeader & AlternateHeaderHasPrimFlag) {
-			firstBytecode = (GIV(newMethod) + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize;
-			primIndex = (byteAt(firstBytecode + 1)) + (((long)(byteAt(firstBytecode + 2))) << 8);
-		}
-		else {
-			primIndex = 0;
-		}
-
-	}
-
-	/* For the method-executing primitives, failure could have been in those primitives or the
-	   primitives of the methods they execute.  Find out which failed by seeing what is in effect. */
-	accessorDepth = primitiveAccessorDepthTable[primIndex];
-	if (((primIndex == PrimNumberExternalCall)
-	 && (primitiveFunctionPointer != primitiveExternalCall))
-	 || ((primIndex == PrimNumberDoExternalCall)
-	 && (primitiveFunctionPointer != primitiveDoNamedPrimitiveWithArgs))) {
-		accessorDepth = ((fetchPointerofObject(2, longAt((GIV(newMethod) + BaseHeaderSize) + (((long)(0 + LiteralStart)) << (shiftForWord()))))) >> 3);
-	}
-	else {
-		assert(saneFunctionPointerForFailureOfPrimIndex(primIndex));
-	}
-	assert(((accessorDepth >= -1) && (accessorDepth <= 4)));
-	if (accessorDepth >= 0) {
-		for (index = 0; index <= GIV(argumentCount); index += 1) {
-			oop = longAt(GIV(stackPointer) + (index * BytesPerWord));
-			if ((oop & (tagMask())) == 0) {
-				if (((longAt(oop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun()))) == 0) {
-					assert(index < GIV(argumentCount));
-					found1 = 1;
-					/* begin followForwarded: */
-					assert(isUnambiguouslyForwarder(oop));
-					referent = longAt((oop + BaseHeaderSize) + (0LL << (shiftForWord())));
-					while (((referent & (tagMask())) == 0)
-					 && (((longAt(referent)) & (classIndexMask())) == (isForwardedObjectClassIndexPun()))) {
-						referent = longAt((referent + BaseHeaderSize) + (0LL << (shiftForWord())));
-					}
-					oop = referent;
-					longAtput(GIV(stackPointer) + (index * BytesPerWord), oop);
-					if (!scannedStackFrame) {
-						scannedStackFrame = 1;
-						followForwardedFrameContentsstackPointer(GIV(framePointer), GIV(stackPointer) + ((GIV(argumentCount) + 1) * BytesPerWord));
-					}
-				}
-				if ((accessorDepth > 0)
-				 && ((((oop & (tagMask())) == 0)
-				 && (isAnyPointerFormat((((usqInt) (longAt(oop))) >> (formatShift())) & (formatMask()))))
-				 && (followForwardedObjectFieldstoDepth(oop, accessorDepth)))) {
-					found1 = 1;
-				}
-			}
-		}
-	}
-	found = found1;
-	if (found
-	 && (recordPrimTrace())) {
-		/* begin fastLogPrim: */
-		GIV(primTraceLog)[GIV(primTraceLogIndex)] = TracePrimitiveRetry;
-		primTraceLogIndex(GIV(primTraceLogIndex) + 1);
-	}
-	return found;
-}
-
-
 /*	Check the log for leaks. The trace log is a circular buffer of pairs of
 	entries. If there is an entry at traceLogIndex - 3 \\ TraceBufferSize it
 	has entries. If
@@ -19341,12 +19225,9 @@
 			GIV(primFailCode) = 0;
 			dispatchFunctionPointer(primitiveFunctionPointer);
 			assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-			/* begin maybeRetryFailureDueToForwarding */
-			if (GIV(primFailCode)
-			 && (checkForAndFollowForwardedPrimitiveState())) {
-				/* begin initPrimCall */
-				GIV(primFailCode) = 0;
-				dispatchFunctionPointer(primitiveFunctionPointer);
+			/* begin maybeRetryPrimitiveOnFailure */
+			if (GIV(primFailCode)) {
+				retryPrimitiveOnFailure();
 			}
 			/* begin maybeFailForLastObjectOverwrite */
 			if (checkAllocFiller) {
@@ -20327,8 +20208,8 @@
     sqInt objToScan;
     sqInt objToScan1;
     sqInt remainder;
-    int scanLargeObject;
-    int scanLargeObject1;
+    sqInt scanLargeObject;
+    sqInt scanLargeObject1;
     sqInt selector;
     sqInt sp;
     sqInt sp1;
@@ -20932,11 +20813,11 @@
     sqInt oop;
     sqInt referent;
     sqInt referent1;
-    int scanLargeObject;
-    int scanLargeObject1;
-    int scanLargeObject2;
-    int scanLargeObject3;
-    int scanLargeObject4;
+    sqInt scanLargeObject;
+    sqInt scanLargeObject1;
+    sqInt scanLargeObject2;
+    sqInt scanLargeObject3;
+    sqInt scanLargeObject4;
     sqInt sp;
     sqInt sp1;
     sqInt sp2;
@@ -22299,8 +22180,8 @@
     sqInt objToScan1;
     sqInt oop;
     sqInt remainder;
-    int scanLargeObject;
-    int scanLargeObject1;
+    sqInt scanLargeObject;
+    sqInt scanLargeObject1;
     sqInt sp;
     sqInt sp1;
 
@@ -25454,12 +25335,9 @@
 	GIV(primFailCode) = 0;
 	dispatchFunctionPointer(primitiveFunctionPointer);
 	assert(maybeLeakCheckExternalPrimCall(GIV(newMethod)));
-	/* begin maybeRetryFailureDueToForwarding */
-	if (GIV(primFailCode)
-	 && (checkForAndFollowForwardedPrimitiveState())) {
-		/* begin initPrimCall */
-		GIV(primFailCode) = 0;
-		dispatchFunctionPointer(primitiveFunctionPointer);
+	/* begin maybeRetryPrimitiveOnFailure */
+	if (GIV(primFailCode)) {
+		retryPrimitiveOnFailure();
 	}
 	/* begin maybeFailForLastObjectOverwrite */
 	if (checkAllocFiller) {
@@ -26839,7 +26717,7 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt alreadyCogged;
     CogMethod *cogMethod;
-    int flags;
+    sqInt flags;
     sqInt methodHeader;
     char *sp;
 
@@ -40930,7 +40808,7 @@
     sqInt oopRcvr;
     sqInt oopResult;
     usqLong result;
-    int resultIsNegative;
+    sqInt resultIsNegative;
     char *sp;
 
 	oopArg = longAt(GIV(stackPointer) + (0 * BytesPerWord));
@@ -42732,7 +42610,7 @@
     sqInt fmt;
     usqInt instBytes;
     sqInt instFormat;
-    usqInt newFormat;
+    sqInt newFormat;
     sqInt normalizedInstFormat;
     usqInt numBytes;
     usqInt numSlots;
@@ -44368,7 +44246,7 @@
     sqInt key;
     sqInt key1;
     sqInt listOffset;
-    usqInt oldCorpse;
+    sqInt oldCorpse;
     sqInt oldList;
     sqInt referent;
     sqInt referrer;
@@ -47001,7 +46879,7 @@
     sqInt referent3;
     sqInt referent4;
     sqInt referent5;
-    usqInt size;
+    sqInt size;
     sqInt sp;
 
 	assert(GIV(becomeEffectsFlags) == 0);
@@ -48602,9 +48480,9 @@
     sqInt o;
     usqInt objOop;
     sqInt objOop1;
-    usqInt prevFree;
+    sqInt prevFree;
     sqInt prevObj;
-    usqInt prevPrevFree;
+    sqInt prevPrevFree;
     sqInt prevPrevObj;
     sqInt slotBytes;
 
@@ -55297,7 +55175,7 @@
     sqInt objOop;
     sqInt objOop1;
     sqInt objToScan;
-    int scanLargeObject;
+    sqInt scanLargeObject;
     sqInt sp;
 
 	numStrongSlots = 0;
@@ -55609,7 +55487,7 @@
     sqInt numStrongSlots;
     sqInt objOop1;
     sqInt objToScan;
-    int scanLargeObject;
+    sqInt scanLargeObject;
     sqInt sp;
 
 	numStrongSlots = 0;
@@ -55895,7 +55773,7 @@
     sqInt objToScan;
     sqInt oop;
     usqInt ptr;
-    int scanLargeObject;
+    sqInt scanLargeObject;
     sqInt sp;
 
 	numStrongSlots = 0;
@@ -56447,22 +56325,22 @@
     sqInt referent2;
     sqInt referent3;
     sqInt referent4;
-    int scanLargeObject;
-    int scanLargeObject1;
-    int scanLargeObject10;
-    int scanLargeObject11;
-    int scanLargeObject12;
-    int scanLargeObject2;
-    int scanLargeObject21;
-    int scanLargeObject3;
-    int scanLargeObject31;
-    int scanLargeObject4;
-    int scanLargeObject41;
-    int scanLargeObject5;
-    int scanLargeObject6;
-    int scanLargeObject7;
-    int scanLargeObject8;
-    int scanLargeObject9;
+    sqInt scanLargeObject;
+    sqInt scanLargeObject1;
+    sqInt scanLargeObject10;
+    sqInt scanLargeObject11;
+    sqInt scanLargeObject12;
+    sqInt scanLargeObject2;
+    sqInt scanLargeObject21;
+    sqInt scanLargeObject3;
+    sqInt scanLargeObject31;
+    sqInt scanLargeObject4;
+    sqInt scanLargeObject41;
+    sqInt scanLargeObject5;
+    sqInt scanLargeObject6;
+    sqInt scanLargeObject7;
+    sqInt scanLargeObject8;
+    sqInt scanLargeObject9;
     usqInt sizeOfUnusedEden;
     sqInt sp;
     sqInt sp1;
@@ -60715,9 +60593,9 @@
     sqInt oop;
     sqInt oop1;
     sqInt p;
-    int scanLargeObject;
-    int scanLargeObject1;
-    int scanLargeObject2;
+    sqInt scanLargeObject;
+    sqInt scanLargeObject1;
+    sqInt scanLargeObject2;
     sqInt size;
     sqInt sp;
     sqInt sp1;
@@ -61624,14 +61502,14 @@
     sqInt obj2;
     sqInt obj21;
     sqInt pigBytes;
-    usqInt prevFree;
-    usqInt prevFreeChunk;
-    usqInt prevPrevFree;
+    sqInt prevFree;
+    sqInt prevFreeChunk;
+    sqInt prevPrevFree;
     sqInt prevPrevFreeChunk;
     sqInt slotBytes;
     sqInt slotBytes1;
     usqInt there;
-    usqInt thisFreeChunk;
+    sqInt thisFreeChunk;
     sqInt usedChunk;
 
 	nextNext = 0;
@@ -65450,7 +65328,7 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     usqInt freeChunk;
     usqInt nextFree;
-    usqInt prevFree;
+    sqInt prevFree;
 
 	if (!((GIV(firstFreeChunk) > 0)
 		 && (GIV(lastFreeChunk) > GIV(firstFreeChunk)))) {
@@ -66939,7 +66817,7 @@
 	mainly by checkFreeSpace. */
 
 	/* SpurMemoryManager>>#totalFreeListBytes */
-static usqInt
+static sqInt
 totalFreeListBytes(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     usqInt bytesInChunk;
@@ -66950,7 +66828,7 @@
     sqInt listNode;
     sqInt nextNode;
     sqInt smallChild;
-    usqInt totalFreeBytes;
+    sqInt totalFreeBytes;
     sqInt treeNode;
     sqInt treeNode1;
 
@@ -67618,7 +67496,7 @@
 static void
 postSnapshot(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt address;
+    usqInt address;
     sqInt bytes;
     usqInt freeChunk;
     sqInt i;
@@ -67681,7 +67559,7 @@
     sqInt limit;
     sqInt newEndOfMemory;
     sqInt next;
-    sqInt node;
+    usqInt node;
     usqInt numSlots;
     usqInt numSlots1;
     SpurSegmentInfo *seg;
@@ -67815,8 +67693,8 @@
     usqLong bridgeSpan;
     sqInt bytesRead;
     usqInt newBase;
-    usqInt nextSegmentSize;
-    usqLong oldBase;
+    sqInt nextSegmentSize;
+    sqInt oldBase;
     SpurSegmentInfo *segInfo;
     sqInt totalBytesRead;
 
@@ -68479,7 +68357,7 @@
     sqInt objOop1;
     sqInt objOop11;
     sqInt objOop2;
-    int ok;
+    sqInt ok;
     sqInt oop;
     sqInt prevObj;
     sqInt prevObj1;
@@ -68977,7 +68855,7 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt i;
     sqInt iLimiT;
-    int ok;
+    sqInt ok;
     sqInt oop;
     long oopOrZero;
 
@@ -69012,7 +68890,7 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     char *callerFP;
     char *frameRcvrOffset;
-    int ok;
+    sqInt ok;
     sqInt oop;
     char *theFP;
     char *theSP;
@@ -69070,7 +68948,7 @@
 checkOkayStackZone(sqInt writeBack)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt i;
-    int ok;
+    sqInt ok;
     StackPage *thePage;
 
 	if (writeBack) {
@@ -74765,11 +74643,9 @@
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt closureOrNil;
     CogMethod *cogMethod;
-    sqInt fieldIndex;
-    sqInt fieldIndex2;
     sqInt frameNumArgs;
     sqInt frameNumArgs2;
-    usqInt i;
+    sqInt i;
     sqInt methodFieldOrObj;
     usqInt numArgs;
     sqInt numSlots;
@@ -74850,7 +74726,6 @@
 	longAtput((theContext + BaseHeaderSize) + (((long)ReceiverIndex) << (shiftForWord())), rcvr);
 	for (i = 1; i <= numArgs; i += 1) {
 		/* begin storePointerUnchecked:ofObject:withValue: */
-		fieldIndex = ReceiverIndex + i;
 		valuePointer = ((((usqInt)(longAt(theFP + FoxMethod)))) < (startOfMemory())
 			? ((i - 1) < ((frameNumArgs = ((mframeCogMethod(theFP))->cmNumArgs)))
 					? longAt((theFP + FoxCallerSavedIP) + ((frameNumArgs - (i - 1)) * BytesPerWord))
@@ -74859,13 +74734,12 @@
 					? longAt((theFP + FoxCallerSavedIP) + ((frameNumArgs2 - (i - 1)) * BytesPerWord))
 					: longAt(((theFP + FoxIFReceiver) - BytesPerWord) + ((frameNumArgs2 - (i - 1)) * BytesPerWord))));
 		assert(!(isForwarded(theContext)));
-		longAtput((theContext + BaseHeaderSize) + (((long)fieldIndex) << (shiftForWord())), valuePointer);
+		longAtput((theContext + BaseHeaderSize) + (((long)(ReceiverIndex + i)) << (shiftForWord())), valuePointer);
 	}
 	for (i = (numArgs + 1); i <= numStack; i += 1) {
 		/* begin storePointerUnchecked:ofObject:withValue: */
-		fieldIndex2 = ReceiverIndex + i;
 		assert(!(isForwarded(theContext)));
-		longAtput((theContext + BaseHeaderSize) + (((long)fieldIndex2) << (shiftForWord())), GIV(nilObj));
+		longAtput((theContext + BaseHeaderSize) + (((long)(ReceiverIndex + i)) << (shiftForWord())), GIV(nilObj));
 	}
 	assert(frameHasContext(theFP));
 	assert((frameOfMarriedContext(theContext)) == theFP);
@@ -78598,6 +78472,161 @@
 }
 
 
+/*	In Spur two cases of primitive failure are handled specially. A primitive
+	may fail due to validation
+	encountering a forwarder. On failure, check the accessorDepth for the
+	primitive and if non-negative
+	scan the args to the depth, following any forwarders. Retry the primitive
+	if any are found. Hence
+	lazily and transparently following forwarders on primtiive failure.
+	Additionally a prmitive might fail
+	due to an allocation failing. Retry if external primitives have failed
+	with PrimErrNoMemory after running
+	first the scavenger and then on a subsequent failure, the global
+	mark-sweep collector. Hence lazily
+	and transparently GC on memory exhaustion. */
+
+	/* StackInterpreter>>#retryPrimitiveOnFailure */
+static sqInt
+retryPrimitiveOnFailure(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    signed char accessorDepth;
+    sqInt canRetry;
+    sqInt firstBytecode;
+    sqInt followDone;
+    sqInt found;
+    sqInt found1;
+    sqInt gcDone;
+    sqInt header;
+    sqInt index;
+    sqInt methodHeader;
+    sqInt oop;
+    sqInt primIndex;
+    sqInt referent;
+    sqInt retried;
+    sqInt retry;
+    sqInt scannedStackFrame;
+
+	gcDone = 0;
+	followDone = (canRetry = (retried = 0));
+	while (1) {
+		retry = 0;
+		if (GIV(primFailCode) == PrimErrNoMemory) {
+			if (((gcDone += 1)) == 1) {
+				canRetry = (primitiveIndexOfMethodheader(GIV(newMethod), methodHeaderOf(GIV(newMethod)))) == PrimNumberExternalCall;
+			}
+			if (canRetry) {
+				if (gcDone == 1) {
+					/* begin scavengingGC */
+					scavengingGCTenuringIf(TenureByAge);
+				}
+				if (gcDone == 2) {
+					fullGC();
+				}
+				retry = gcDone <= 2;
+			}
+		}
+		else {
+			if (!followDone) {
+				followDone = 1;
+				/* begin checkForAndFollowForwardedPrimitiveState */
+				if (recordPrimTrace()) {
+					/* begin fastLogPrim: */
+					GIV(primTraceLog)[GIV(primTraceLogIndex)] = TracePrimitiveFailure;
+					primTraceLogIndex(GIV(primTraceLogIndex) + 1);
+				}
+				assert(failed());
+				found1 = (scannedStackFrame = 0);
+				if ((((GIV(newMethod)) & 7) == 1)) {
+					primIndex = (GIV(newMethod) >> 3);
+				}
+				else {
+					assert(GIV(argumentCount) == (argumentCountOf(GIV(newMethod))));
+					/* begin primitiveIndexOfMethod:header: */
+					assert(isCompiledMethod(GIV(newMethod)));
+					header = longAt((GIV(newMethod) + BaseHeaderSize) + (((long)HeaderIndex) << (shiftForWord())));
+					if ((((header) & 7) == 1)) {
+						methodHeader = header;
+					}
+					else {
+						assert((((usqInt)header)) < GIV(newSpaceStart));
+						assert((((((CogMethod *) header))->objectHeader)) == (nullHeaderForMachineCodeMethod()));
+						methodHeader = ((((CogMethod *) header))->methodHeader);
+					}
+					if (methodHeader & AlternateHeaderHasPrimFlag) {
+						firstBytecode = (GIV(newMethod) + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize;
+						primIndex = (byteAt(firstBytecode + 1)) + (((long)(byteAt(firstBytecode + 2))) << 8);
+					}
+					else {
+						primIndex = 0;
+					}
+
+				}
+
+				/* For the method-executing primitives, failure could have been in those primitives or the
+				   primitives of the methods they execute.  Find out which failed by seeing what is in effect. */
+				accessorDepth = primitiveAccessorDepthTable[primIndex];
+				if (((primIndex == PrimNumberExternalCall)
+				 && (primitiveFunctionPointer != primitiveExternalCall))
+				 || ((primIndex == PrimNumberDoExternalCall)
+				 && (primitiveFunctionPointer != primitiveDoNamedPrimitiveWithArgs))) {
+					accessorDepth = ((fetchPointerofObject(2, longAt((GIV(newMethod) + BaseHeaderSize) + (((long)(0 + LiteralStart)) << (shiftForWord()))))) >> 3);
+				}
+				else {
+					assert(saneFunctionPointerForFailureOfPrimIndex(primIndex));
+				}
+				assert(((accessorDepth >= -1) && (accessorDepth <= 4)));
+				if (accessorDepth >= 0) {
+					for (index = 0; index <= GIV(argumentCount); index += 1) {
+						oop = longAt(GIV(stackPointer) + (index * BytesPerWord));
+						if ((oop & (tagMask())) == 0) {
+							if (((longAt(oop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun()))) == 0) {
+								assert(index < GIV(argumentCount));
+								found1 = 1;
+								/* begin followForwarded: */
+								assert(isUnambiguouslyForwarder(oop));
+								referent = longAt((oop + BaseHeaderSize) + (0LL << (shiftForWord())));
+								while (((referent & (tagMask())) == 0)

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list