[Vm-dev] [commit][3107] CogVM source as per VMMaker.oscog-eem.909

commits at squeakvm.org commits at squeakvm.org
Fri Oct 24 00:37:57 UTC 2014


Revision: 3107
Author:   eliot
Date:     2014-10-23 17:37:55 -0700 (Thu, 23 Oct 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.909

Spur:
Refactor the Spur image segment code into smaller methods.  Collect the classes
in a segment at the start of the seg, immediately following the root obj, to
ease postponing adding cxlasses in the seg to the class table until after
validation.  Byte swap image segments in the load primitive if required,
as is expected by the ImageSegment code.

Oops, markStack pop order is LIFO.  Explicitly put the roots array first in the
reachable objects array that populates a segment.
testImageSegmentsShouldBeWritableToaFile now succeeds & the system stays alive.

All:
Print slots of word objects in longPrintOop:

Unix:
Quote the LD_LIBRARY_PATH setting to tolerate directory names  with spaces.

Modified Paths:
--------------
    branches/Cog/nscogsrc/vm/cointerp.c
    branches/Cog/nscogsrc/vm/cointerp.h
    branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/platforms/unix/config/bin.squeak.sh.in
    branches/Cog/platforms/unix/config/squeak.sh.in
    branches/Cog/sistasrc/vm/cointerp.c
    branches/Cog/sistasrc/vm/cointerp.h
    branches/Cog/sistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.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/nscogsrc/vm/cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.c	2014-10-22 02:17:13 UTC (rev 3106)
+++ branches/Cog/nscogsrc/vm/cointerp.c	2014-10-24 00:37:55 UTC (rev 3107)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
    from
-	CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -2085,7 +2085,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.906";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.909";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -46794,6 +46794,7 @@
     sqInt header;
     sqInt header1;
     sqInt i;
+    sqInt iLimiT;
     sqInt index;
     sqInt lastIndex;
     sqInt len;
@@ -46895,6 +46896,22 @@
 		return;
 	}
 	if (((fmt >= 6) && (fmt <= (8 - 1)))) {
+		for (i = 0, iLimiT = (((((((usqInt) (numBytesOf(oop))) >> 2) < 256) ? (((usqInt) (numBytesOf(oop))) >> 2) : 256)) - 1); i <= iLimiT; i += 1) {
+			fieldOop = long32At((oop + BaseHeaderSize) + (i << 2));
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			printNum(i - 1);
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			printHex(fieldOop);
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			/* begin cr */
+			printf("\n");
+		}
 		return;
 	}
 	startIP = (((lastPointerOf(oop)) + BytesPerOop) - BaseHeaderSize) / BytesPerOop;

Modified: branches/Cog/nscogsrc/vm/cointerp.h
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.h	2014-10-22 02:17:13 UTC (rev 3106)
+++ branches/Cog/nscogsrc/vm/cointerp.h	2014-10-24 00:37:55 UTC (rev 3107)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
  */
 
 

Modified: branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-10-22 02:17:13 UTC (rev 3106)
+++ branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2014-10-24 00:37:55 UTC (rev 3107)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
    from
-	CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -2088,7 +2088,7 @@
 	/* 574 */ (void (*)(void))0,
 	/* 575 */ (void (*)(void))0,
  0 };
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.906";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.909";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -46803,6 +46803,7 @@
     sqInt header;
     sqInt header1;
     sqInt i;
+    sqInt iLimiT;
     sqInt index;
     sqInt lastIndex;
     sqInt len;
@@ -46904,6 +46905,22 @@
 		return;
 	}
 	if (((fmt >= 6) && (fmt <= (8 - 1)))) {
+		for (i = 0, iLimiT = (((((((usqInt) (numBytesOf(oop))) >> 2) < 256) ? (((usqInt) (numBytesOf(oop))) >> 2) : 256)) - 1); i <= iLimiT; i += 1) {
+			fieldOop = long32At((oop + BaseHeaderSize) + (i << 2));
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			printNum(i - 1);
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			printHex(fieldOop);
+			/* begin space */
+			/* begin printChar: */
+			putchar(' ');
+			/* begin cr */
+			printf("\n");
+		}
 		return;
 	}
 	startIP = (((lastPointerOf(oop)) + BytesPerOop) - BaseHeaderSize) / BytesPerOop;

Modified: branches/Cog/nsspursrc/vm/cointerp.c
===================================================================
--- branches/Cog/nsspursrc/vm/cointerp.c	2014-10-22 02:17:13 UTC (rev 3106)
+++ branches/Cog/nsspursrc/vm/cointerp.c	2014-10-24 00:37:55 UTC (rev 3107)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
    from
-	CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d
+	CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.906 uuid: aaa9ffc5-3dc3-455d-b550-92988ab90a8d " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.909 uuid: 0d4fb242-44a2-408b-bc90-a737cfdd364d " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -1058,6 +1058,7 @@
 static sqInt isonObjStack(sqInt oop, sqInt objStack) NoDbgRegParms;
 static sqInt keyOfEphemeron(sqInt objOop) NoDbgRegParms;
 static sqInt knownClassAtIndex(sqInt classIndex) NoDbgRegParms;
+static sqInt lastClassIndexPun(void);
 sqInt lastPointerOfWhileSwizzling(sqInt objOop);
 sqInt lastPointerOf(sqInt objOop);
 sqInt leakCheckBecome(void);
@@ -1070,10 +1071,11 @@
 static sqInt lengthOfformat(sqInt objOop, sqInt fmt) NoDbgRegParms;
 sqInt literalCountOfMethodHeader(sqInt header);
 sqInt literalCountOf(sqInt methodPointer);
-static sqInt loadImageSegmentFromoutPointers(sqInt segmentWordArrayArg, sqInt outPointerArray) NoDbgRegParms;
+static sqInt loadImageSegmentFromoutPointers(sqInt segmentWordArray, sqInt outPointerArray) NoDbgRegParms;
 void longPrintInstancesOf(sqInt aClassOop);
 void longPrintInstancesWithClassIndex(sqInt classIndex);
 void longPrintReferencesTo(sqInt anOop);
+static sqInt mapOopsFromtooutPointersoutHashes(sqInt segStart, sqInt segAddr, sqInt outPointerArray, sqInt savedOutHashes) NoDbgRegParms;
 static void markAndTraceClassOf(sqInt objOop) NoDbgRegParms;
 static void markAndTraceObjStackandContents(sqInt stackOrNil, sqInt markAndTraceContents) NoDbgRegParms;
 void markAndTrace(sqInt objOop);
@@ -1527,8 +1529,8 @@
 _iss usqInt endOfMemory;
 _iss sqInt weaklingStack;
 _iss usqInt newSpaceStart;
+_iss SpurSegmentInfo * segments;
 _iss sqInt needGCFlag;
-_iss SpurSegmentInfo * segments;
 _iss sqInt trueObj;
 _iss sqInt falseObj;
 _iss sqInt remapBufferCount;
@@ -1706,9 +1708,9 @@
 #endif
 #endif
 static void (*primitiveFunctionPointer)();
-sqInt checkForLeaks;
 sqInt maxLiteralCountForCompile = MaxLiteralCountForCompile /* 60 */;
 jmp_buf reenterInterpreter; /* private export */;
+sqInt checkForLeaks;
 sqInt checkAllocFiller;
 sqInt inIOProcessEvents;
 sqInt desiredEdenBytes;
@@ -2333,7 +2335,7 @@
 /*540*/	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 /*560*/	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0,-1,-1
 	};
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.906";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.909";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -47136,7 +47138,8 @@
 
 /*	Copy objOop into the segment beginning at segAddr, and forward it to the
 	copy. If it is a class in the class table, set the copy's hash to 0 for
-	reassignment on load.
+	reassignment on load,
+	and mark it as a class by setting its isRemembered bit.
 	Answer the next segmentAddr if successful. Answer an appropriate error
 	code if not */
 /*	Copy the object... */
@@ -47173,6 +47176,9 @@
 		flag("endianness");
 		assert(((0 >= 0) && (0 <= (identityHashHalfWordMask()))));
 		longAtput(copy + 4, ((((longAt(copy + 4)) | 0x3FFFFF) - 0x3FFFFF)) + 0);
+		/* begin setIsRememberedOf:to: */
+		flag("endianness");
+		longAtput(copy, (longAt(copy)) | (1 << 29));
 	}
 	newOop = (copy - segStart) / 8;
 	if (newOop > 0x3FFFFF) {
@@ -50763,6 +50769,19 @@
 }
 
 
+/*	Class puns are class indices not used by any class. There is an entry
+	for the pun that refers to the notional class of objects with this class
+	index. But because the index doesn't match the class it won't show up
+	in allInstances, hence hiding the object with a pun as its class index.
+	The puns occupy indices 16 through 31. */
+
+static sqInt
+lastClassIndexPun(void)
+{
+	return 0x1F;
+}
+
+
 /*	Answer the byte offset of the last pointer field of the given object.
 	Works with CompiledMethods, as well as ordinary objects.
 	Does not examine the stack pointer of contexts to be sure to swizzle
@@ -51016,33 +51035,47 @@
 	just fail if endinanness is wrong. */
 
 static sqInt
-loadImageSegmentFromoutPointers(sqInt segmentWordArrayArg, sqInt outPointerArray)
+loadImageSegmentFromoutPointers(sqInt segmentWordArray, sqInt outPointerArray)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt addr;
+    sqInt addr1;
     sqInt classIndex;
+    sqInt classIndex1;
+    sqInt classOop;
+    sqInt classRef;
     sqInt errorCode;
-    sqInt firstNeedingPostProcessing;
+    sqInt errorCode1;
     sqInt hash;
     sqInt i;
     sqInt iLimiT;
-    sqInt newObj;
-    usqInt numBytes;
+    sqInt mappedOop;
     usqInt numOutPointers;
     usqInt numSlots;
     usqInt numSlots1;
+    usqInt numSlots11;
+    usqInt numSlots12;
     usqInt numSlots2;
     usqInt numSlots3;
+    usqInt numSlots4;
+    usqInt numSlots5;
     sqInt objOop;
+    sqInt objOop1;
+    sqInt objOop2;
     sqInt oldClone;
     sqInt oop;
-    sqInt outPointer;
-    sqInt segLimit;
-    sqInt segmentWordArray;
-    sqInt segStart;
+    sqInt oop1;
+    sqInt segmentLimit;
+    sqInt segmentStart;
     sqInt segVersion;
+    sqInt slotBytes;
+    sqInt slotBytes1;
+    sqInt stopAddr;
+    sqInt stopAddr1;
     sqInt topHashBit;
+    sqInt topHashBit1;
     sqInt topOopBit;
 
-	segVersion = longAt(segmentWordArrayArg + BaseHeaderSize);
+	segVersion = longAt(segmentWordArray + BaseHeaderSize);
 	if (!(((segVersion & 0xFFFF) == (imageFormatVersion()))
 		 || ((!1)
 		 && ((segVersion & 0xFFFF) == ((BytesPerWord == 4
@@ -51051,239 +51084,250 @@
 
 		/* low 2 bytes */
 
-		return PrimErrBadArgument;
-	}
-	if ((byteAt(segmentWordArrayArg + 7)) == 0xFF) {
-		segmentWordArray = segmentWordArrayArg;
-	}
-	else {
-		/* begin allocateSlots:format:classIndex: */
-		if ((0xFF + 1) >= 0xFF) {
-			;
-			newObj = GIV(freeStart) + BaseHeaderSize;
-			numBytes = (BaseHeaderSize + BaseHeaderSize) + (((0xFF + 1) + ((0xFF + 1) & 1)) * 4);
+		/* begin reverseBytesFrom:to: */
+		/* begin addressAfter: */
+		/* begin numSlotsOfAny: */
+		numSlots11 = byteAt(segmentWordArray + 7);
+		numSlots3 = (numSlots11 == 0xFF
+			? longAt(segmentWordArray - BaseHeaderSize)
+			: numSlots11);
+		slotBytes1 = (numSlots3 == 0
+			? 8
+			: (numSlots3 + (numSlots3 & 1)) << 2);
+		stopAddr1 = (segmentWordArray + BaseHeaderSize) + slotBytes1;
+		addr1 = segmentWordArray + BaseHeaderSize;
+		while ((((usqInt) addr1)) < (((usqInt) stopAddr1))) {
+			longAtput(addr1, ((((((usqInt) (longAt(addr1)) >> 24)) & Byte0Mask) + ((((usqInt) (longAt(addr1)) >> 8)) & Byte1Mask)) + ((((usqInt) (longAt(addr1)) << 8)) & Byte2Mask)) + ((((usqInt) (longAt(addr1)) << 24)) & Byte3Mask));
+			addr1 += BytesPerWord;
 		}
-		else {
-			newObj = GIV(freeStart);
-			numBytes = BaseHeaderSize + (((0xFF + 1) <= 1
-	? 8
-	: ((0xFF + 1) + ((0xFF + 1) & 1)) * 4));
-		}
-		if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) {
-			if (!GIV(needGCFlag)) {
-				/* begin scheduleScavenge */
-				GIV(needGCFlag) = 1;
-				forceInterruptCheck();
-			}
-			segmentWordArray = allocateSlotsInOldSpacebytesformatclassIndex(0xFF + 1, numBytes, (((usqInt) (longAt(segmentWordArrayArg))) >> 24) & 0x1F, (longAt(segmentWordArrayArg)) & 0x3FFFFF);
-			goto l1;
-		}
-		if ((0xFF + 1) >= 0xFF) {
+		segVersion = longAt(segmentWordArray + BaseHeaderSize);
+		if (!(((segVersion & 0xFFFF) == (imageFormatVersion()))
+			 || ((!1)
+			 && ((segVersion & 0xFFFF) == ((BytesPerWord == 4
+	? 6504
+	: 68002)))))) {
 
-			/* for header parsing we put a saturated slot count in the prepended overflow size word */
+			/* low 2 bytes */
 
-			flag("endianness");
-			longAtput(GIV(freeStart), 0xFF + 1);
-			longAtput(GIV(freeStart) + 4, 0xFF << 24);
-			long64Atput(newObj, (((((usqLong) 0xFF)) << 56) + (((((usqInt) (longAt(segmentWordArrayArg))) >> 24) & 0x1F) << 24)) + ((longAt(segmentWordArrayArg)) & 0x3FFFFF));
+			/* begin reverseBytesFrom:to: */
+			/* begin addressAfter: */
+			/* begin numSlotsOfAny: */
+			numSlots1 = byteAt(segmentWordArray + 7);
+			numSlots2 = (numSlots1 == 0xFF
+				? longAt(segmentWordArray - BaseHeaderSize)
+				: numSlots1);
+			slotBytes = (numSlots2 == 0
+				? 8
+				: (numSlots2 + (numSlots2 & 1)) << 2);
+			stopAddr = (segmentWordArray + BaseHeaderSize) + slotBytes;
+			addr = segmentWordArray + BaseHeaderSize;
+			while ((((usqInt) addr)) < (((usqInt) stopAddr))) {
+				longAtput(addr, ((((((usqInt) (longAt(addr)) >> 24)) & Byte0Mask) + ((((usqInt) (longAt(addr)) >> 8)) & Byte1Mask)) + ((((usqInt) (longAt(addr)) << 8)) & Byte2Mask)) + ((((usqInt) (longAt(addr)) << 24)) & Byte3Mask));
+				addr += BytesPerWord;
+			}
+			return PrimErrBadArgument;
 		}
-		else {
-			long64Atput(newObj, (((((usqLong) (0xFF + 1))) << 56) + (((((usqInt) (longAt(segmentWordArrayArg))) >> 24) & 0x1F) << 24)) + ((longAt(segmentWordArrayArg)) & 0x3FFFFF));
-		}
-		assert((numBytes % (allocationUnit())) == 0);
-		assert((newObj % (allocationUnit())) == 0);
-		GIV(freeStart) += numBytes;
-		segmentWordArray = newObj;
-	l1:	/* end allocateSlots:format:classIndex: */;
-		if (!(segmentWordArray)) {
-			return PrimErrNoMemory;
-		}
-		memcpy(segmentWordArray + BaseHeaderSize, segmentWordArrayArg + BaseHeaderSize, (numSlotsOf(segmentWordArrayArg)) * BytesPerOop);
 	}
-	segStart = (segmentWordArray + BaseHeaderSize) + 8;
+	segmentStart = (segmentWordArray + BaseHeaderSize) + 8;
 
-	/* scan through mapping oops and validating class references.
-	   Defer entering any class objects into the class table and/or
-	   pinning objects until a second pass. */
+	/* Notionally reverse the Byte type objects if the data is from opposite endian machine.
+	   Test top byte.  $d on the Mac or $s on the PC.  Rest of word is equal.  If Spur is ever
+	   ported to big-endian machines then the segment may have to be byte/word swapped,
+	   but so far it only runs on little-endian machines, so for now just fail if endinanness is wrong. */
 
-	segLimit = (((numSlotsOf(segmentWordArrayArg)) * BytesPerOop) + segmentWordArray) + BaseHeaderSize;
+	segmentLimit = (((numSlotsOf(segmentWordArray)) * BytesPerOop) + segmentWordArray) + BaseHeaderSize;
+	flag("endianness");
+	if ((((usqInt) segVersion) >> 16) != (((usqInt) (imageSegmentVersion())) >> 16)) {
+
+		/* Reverse the byte-type objects once */
+
+		return PrimErrBadArgument;
+
+	}
+	/* begin mapOopsAndValidateClassRefsFrom:to:outPointers: */
 	/* begin numSlotsOf: */
 	flag("endianness");
 	assert((classIndexOf(outPointerArray)) > (isForwardedObjectClassIndexPun()));
-	numSlots1 = byteAt(outPointerArray + 7);
-	numOutPointers = (numSlots1 == 0xFF
+	numSlots4 = byteAt(outPointerArray + 7);
+	numOutPointers = (numSlots4 == 0xFF
 		? longAt(outPointerArray - BaseHeaderSize)
-		: numSlots1);
-	firstNeedingPostProcessing = 0;
+		: numSlots4);
 	topHashBit = (((22 - 1) < 0) ? ((usqInt) 1 >> -(22 - 1)) : ((usqInt) 1 << (22 - 1)));
 	topOopBit = ((((BytesPerOop * 8) - 1) < 0) ? ((usqInt) 1 >> -((BytesPerOop * 8) - 1)) : ((usqInt) 1 << ((BytesPerOop * 8) - 1)));
 	/* begin objectStartingAt: */
-	numSlots2 = byteAt(segStart + 7);
-	objOop = (numSlots2 == 0xFF
-		? segStart + BaseHeaderSize
-		: segStart);
-	while (objOop < segLimit) {
-		if ((((((usqInt) (longAt(objOop))) >> 29) & 1) != 0)
-		 || (((((usqInt) (longAt(objOop + 4))) >> 23) & 1) != 0)) {
-			return PrimErrInappropriate;
+	numSlots12 = byteAt(segmentStart + 7);
+	objOop1 = (numSlots12 == 0xFF
+		? segmentStart + BaseHeaderSize
+		: segmentStart);
+	while (objOop1 < segmentLimit) {
+		if (((((usqInt) (longAt(objOop1 + 4))) >> 23) & 1) != 0) {
+			errorCode = PrimErrInappropriate;
+			goto l2;
 		}
-		if ((firstNeedingPostProcessing == 0)
-		 && ((((((usqInt) objOop)) < (((usqInt) GIV(newSpaceLimit))))
-		 && ((((usqInt) objOop)) >= (((usqInt) GIV(newSpaceStart)))))
-		 && (((((usqInt) (longAt(objOop))) >> 30) & 1) != 0))) {
-			firstNeedingPostProcessing = objOop;
-		}
-		classIndex = (longAt(objOop)) & 0x3FFFFF;
+
+		/* validate the class ref, but don't update it until any internal classes have been added to the class table. */
+
+		classIndex = (longAt(objOop1)) & 0x3FFFFF;
 		if (classIndex & topHashBit) {
 			if ((classIndex - topHashBit) >= numOutPointers) {
-				return PrimErrBadIndex;
+				errorCode = PrimErrBadIndex;
+				goto l2;
 			}
-			outPointer = longAt((outPointerArray + BaseHeaderSize) + ((classIndex - topHashBit) << 2));
-			hash = (longAt(outPointer + 4)) & 0x3FFFFF;
+			mappedOop = longAt((outPointerArray + BaseHeaderSize) + ((classIndex - topHashBit) << 2));
+			hash = (longAt(mappedOop + 4)) & 0x3FFFFF;
 			if (!((hash > 0x1F)
-				 && ((classOrNilAtIndex(hash)) == outPointer))) {
-				return PrimErrInappropriate;
+				 && ((classOrNilAtIndex(hash)) == mappedOop))) {
+				errorCode = PrimErrInappropriate;
+				goto l2;
 			}
-			/* begin setClassIndexOf:to: */
-			assert(((hash >= 0) && (hash <= (classIndexMask()))));
-			flag("endianness");
-			longAtput(objOop, ((longAt(objOop)) & (~0x3FFFFF)) + hash);
 		}
 		else {
 
 			/* The class is contained within the segment. */
 
-			if (((oop = (classIndex * 8) + segStart)) >= segLimit) {
-				return PrimErrBadIndex;
+			if (((oop1 = (classIndex * 8) + segmentStart)) >= segmentLimit) {
+				errorCode = PrimErrBadIndex;
+				goto l2;
 			}
-			if (((longAt(oop + 4)) & 0x3FFFFF) != 0) {
-				return PrimErrInappropriate;
+			if (((longAt(oop1 + 4)) & 0x3FFFFF) != 0) {
+				errorCode = PrimErrInappropriate;
+				goto l2;
 			}
-			/* begin setIsRememberedOf:to: */
-			flag("endianness");
-			longAtput(objOop, (longAt(objOop)) | (1 << 29));
-			if (firstNeedingPostProcessing == 0) {
-				firstNeedingPostProcessing = objOop;
-			}
 		}
-		for (i = 0, iLimiT = ((numPointerSlotsOf(objOop)) - 1); i <= iLimiT; i += 1) {
-			oop = longAt((objOop + BaseHeaderSize) + (i << 2));
-			if ((oop & 3) == 0) {
-				if ((oop & (8 - 1)) != 0) {
-					return PrimErrInappropriate;
-				}
-				if (oop & topOopBit) {
-					if ((oop / BytesPerOop) >= numOutPointers) {
-						return PrimErrBadIndex;
+		for (i = 0, iLimiT = ((numPointerSlotsOf(objOop1)) - 1); i <= iLimiT; i += 1) {
+			oop1 = longAt((objOop1 + BaseHeaderSize) + (i << 2));
+			if ((oop1 & 3) == 0) {
+				if (oop1 & topOopBit) {
+					if (((oop1 = (oop1 - topOopBit) / BytesPerOop)) >= numOutPointers) {
+						errorCode = PrimErrBadIndex;
+						goto l2;
 					}
-					outPointer = longAt((outPointerArray + BaseHeaderSize) + ((oop / BytesPerOop) << 2));
-					/* begin storePointerUnchecked:ofObject:withValue: */
-					assert(!(isForwarded(objOop)));
-					longAtput((objOop + BaseHeaderSize) + (i << 2), outPointer);
+					mappedOop = longAt((outPointerArray + BaseHeaderSize) + (oop1 << 2));
 				}
 				else {
-					if ((oop + segStart) >= segLimit) {
-						return PrimErrBadIndex;
+					if ((oop1 & (8 - 1)) != 0) {
+						errorCode = PrimErrInappropriate;
+						goto l2;
 					}
-					/* begin storePointerUnchecked:ofObject:withValue: */
-					assert(!(isForwarded(objOop)));
-					longAtput((objOop + BaseHeaderSize) + (i << 2), oop + segStart);
+					if (((mappedOop = oop1 + segmentStart)) >= segmentLimit) {
+						errorCode = PrimErrBadIndex;
+						goto l2;
+					}
 				}
+				/* begin storePointerUnchecked:ofObject:withValue: */
+				assert(!(isForwarded(objOop1)));
+				longAtput((objOop1 + BaseHeaderSize) + (i << 2), mappedOop);
 			}
 		}
-		objOop = objectAfterlimit(objOop, segLimit);
+		objOop1 = objectAfterlimit(objOop1, segmentLimit);
 	}
-	if (firstNeedingPostProcessing != 0) {
-		objOop = firstNeedingPostProcessing;
-		assert(isRemembered(objOop));
-		while (objOop < segLimit) {
-			if (((((usqInt) (longAt(objOop))) >> 29) & 1) != 0) {
-				/* begin setIsRememberedOf:to: */
+	errorCode = 0;
+l2:	/* end mapOopsAndValidateClassRefsFrom:to:outPointers: */;
+	if (errorCode != 0) {
+		return errorCode;
+	}
+	/* begin enterClassesIntoClassTableFrom:to: */
+	objOop = objectAfter(objectStartingAt(segmentStart));
+	while ((objOop < segmentLimit)
+	 && (((((usqInt) (longAt(objOop))) >> 29) & 1) != 0)) {
+		/* begin setIsRememberedOf:to: */
+		flag("endianness");
+		longAtput(objOop, (longAt(objOop)) & (~(1 << 29)));
+		if (((errorCode1 = enterIntoClassTable(objOop))) != 0) {
+			oop = objOop;
+			objOop = objectAfter(objectStartingAt(segmentStart));
+			while (objOop < oop) {
+				expungeFromClassTable(objOop);
+				objOop = objectAfterlimit(objOop, segmentLimit);
+			}
+			errorCode = errorCode1;
+			goto l1;
+		}
+		objOop = objectAfterlimit(objOop, segmentLimit);
+	}
+	errorCode = 0;
+l1:	/* end enterClassesIntoClassTableFrom:to: */;
+	if (errorCode != 0) {
+		return errorCode;
+	}
+	/* begin assignClassIndicesAndPinFrom:to:outPointers: */
+	topHashBit1 = (((22 - 1) < 0) ? ((usqInt) 1 >> -(22 - 1)) : ((usqInt) 1 << (22 - 1)));
+	/* begin objectStartingAt: */
+	numSlots5 = byteAt(segmentStart + 7);
+	objOop2 = (numSlots5 == 0xFF
+		? segmentStart + BaseHeaderSize
+		: segmentStart);
+	while (objOop2 < segmentLimit) {
+		classRef = (longAt(objOop2)) & 0x3FFFFF;
+		classOop = (classRef & topHashBit1
+			? longAt((outPointerArray + BaseHeaderSize) + ((classRef - topHashBit1) << 2))
+			: (classRef * 8) + segmentStart);
+		classIndex1 = (longAt(classOop + 4)) & 0x3FFFFF;
+		assert((classIndex1 > (lastClassIndexPun()))
+		 && ((classOrNilAtIndex(classIndex1)) == classOop));
+		/* begin setClassIndexOf:to: */
+		assert(((classIndex1 >= 0) && (classIndex1 <= (classIndexMask()))));
+		flag("endianness");
+		longAtput(objOop2, ((longAt(objOop2)) & (~0x3FFFFF)) + classIndex1);
+		if ((((((usqInt) objOop2)) < (((usqInt) GIV(newSpaceLimit))))
+		 && ((((usqInt) objOop2)) >= (((usqInt) GIV(newSpaceStart)))))
+		 && (((((usqInt) (longAt(objOop2))) >> 30) & 1) != 0)) {
+			oldClone = cloneInOldSpaceForPinning(objOop2);
+			if (oldClone != 0) {
+				/* begin setIsPinnedOf:to: */
 				flag("endianness");
-				longAtput(objOop, (longAt(objOop)) & (~(1 << 29)));
-				classIndex = (longAt(objOop)) & 0x3FFFFF;
-				assert(!((classIndex & topHashBit)));
-				oop = (classIndex * 8) + segStart;
-				if (((hash = (longAt(oop + 4)) & 0x3FFFFF)) == 0) {
-
-					/* The class needs to be added to the classTable */
-
-					if (((errorCode = enterIntoClassTable(oop))) != 0) {
-						/* begin objectStartingAt: */
-						numSlots = byteAt(segStart + 7);
-						objOop = (numSlots == 0xFF
-							? segStart + BaseHeaderSize
-							: segStart);
-						while (objOop < segLimit) {
-							hash = (longAt(objOop + 4)) & 0x3FFFFF;
-							(hash > 0x1F)
-							 && ((((classOrNilAtIndex(hash)) == objOop
-									? expungeFromClassTable(objOop)
-									: 0),
-							(objOop = objectAfterlimit(objOop, segLimit))));
-						}
-						return errorCode;
-					}
-					hash = (longAt(oop + 4)) & 0x3FFFFF;
-				}
-				/* begin setClassIndexOf:to: */
-				assert(((hash >= 0) && (hash <= (classIndexMask()))));
+				longAtput(oldClone, (longAt(oldClone)) | (1 << 30));
+				/* begin forward:to: */
+				/* begin set:classIndexTo:formatTo: */
+				assert(((8 >= 0) && (8 <= (classIndexMask()))));
+				assert(((7 >= 0) && (7 <= (formatMask()))));
 				flag("endianness");
-				longAtput(objOop, ((longAt(objOop)) & (~0x3FFFFF)) + hash);
-			}
-			if ((((((usqInt) objOop)) < (((usqInt) GIV(newSpaceLimit))))
-			 && ((((usqInt) objOop)) >= (((usqInt) GIV(newSpaceStart)))))
-			 && (((((usqInt) (longAt(objOop))) >> 30) & 1) != 0)) {
-				oldClone = cloneInOldSpaceForPinning(objOop);
-				if (oldClone != 0) {
-					/* begin setIsPinnedOf:to: */
-					flag("endianness");
-					longAtput(oldClone, (longAt(oldClone)) | (1 << 30));
-					/* begin forward:to: */
-					/* begin set:classIndexTo:formatTo: */
-					assert(((8 >= 0) && (8 <= (classIndexMask()))));
-					assert(((7 >= 0) && (7 <= (formatMask()))));
-					flag("endianness");
-					longAtput(objOop, ((longAt(objOop)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
-					/* begin storePointer:ofForwarder:withValue: */
-					assert(isForwarded(objOop));
-					assert(!(isOopForwarded(oldClone)));
-					if (isOldObject(objOop)) {
+				longAtput(objOop2, ((longAt(objOop2)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
+				/* begin storePointer:ofForwarder:withValue: */
+				assert(isForwarded(objOop2));
+				assert(!(isOopForwarded(oldClone)));
+				if (isOldObject(objOop2)) {
 
-						/* most stores into young objects */
+					/* most stores into young objects */
 
-						if (((oldClone & 3) == 0)
-						 && ((((usqInt) oldClone)) < (((usqInt) GIV(newSpaceLimit))))) {
-							/* begin possibleRootStoreInto: */
-							if (!(((((usqInt) (longAt(objOop))) >> 29) & 1) != 0)) {
-								remember(objOop);
-							}
+					if (((oldClone & 3) == 0)
+					 && ((((usqInt) oldClone)) < (((usqInt) GIV(newSpaceLimit))))) {
+						/* begin possibleRootStoreInto: */
+						if (!(((((usqInt) (longAt(objOop2))) >> 29) & 1) != 0)) {
+							remember(objOop2);
 						}
 					}
-					longAtput((objOop + BaseHeaderSize) + (0 << 2), oldClone);
-					if ((byteAt(objOop + 7)) == 0) {
-						/* begin setRawNumSlotsOf:to: */
-						flag("endian");
-						byteAtput(objOop + 7, 1);
-					}
 				}
+				longAtput((objOop2 + BaseHeaderSize) + (0 << 2), oldClone);
+				if ((byteAt(objOop2 + 7)) == 0) {
+					/* begin setRawNumSlotsOf:to: */
+					flag("endian");
+					byteAtput(objOop2 + 7, 1);
+				}
 			}
-			objOop = objectAfterlimit(objOop, segLimit);
 		}
+		objOop2 = objectAfterlimit(objOop2, segmentLimit);
 	}
-	/* begin setOverflowNumSlotsOf:to: */
-	flag("endian");
-	long32Atput(segmentWordArray - BaseHeaderSize, 0);
+	if ((byteAt(segmentWordArray + 7)) == 0xFF) {
+		/* begin setOverflowNumSlotsOf:to: */
+		flag("endian");
+		long32Atput(segmentWordArray - BaseHeaderSize, 0);
+	}
+	else {
+		/* begin setRawNumSlotsOf:to: */
+		flag("endian");
+		byteAtput(segmentWordArray + 7, 0);
+	}
 	if ((checkForLeaks & 16) != 0) {
 		/* begin runLeakCheckerForFullGC: */
 		runLeakCheckerForFullGCexcludeUnmarkedNewSpaceObjsclassIndicesShouldBeValid(1, 0, 1);
 		/* return self */
 	}
 	/* begin objectStartingAt: */
-	numSlots3 = byteAt(segStart + 7);
-	return (numSlots3 == 0xFF
-		? segStart + BaseHeaderSize
-		: segStart);
+	numSlots = byteAt(segmentStart + 7);
+	return (numSlots == 0xFF
+		? segmentStart + BaseHeaderSize
+		: segmentStart);
 }
 
 
@@ -51586,6 +51630,185 @@
 }
 
 
+/*	Now scan, adding out pointers to the outPointersArray; all objects in
+	arrayOfObjects have their hashes set to point to their copies in
+	segmentWordArray. Answer the outIndex
+	if the scan succeded, otherwise answer -1. It will fail if outPointers is
+	too small. */
+
+static sqInt
+mapOopsFromtooutPointersoutHashes(sqInt segStart, sqInt segAddr, sqInt outPointerArray, sqInt savedOutHashes)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classIndex;
+    sqInt classTablePage;
+    sqInt hash;
+    sqInt hash1;
+    sqInt i;
+    sqInt iLimiT;
+    sqInt numSlots;
+    usqInt numSlots1;
+    usqInt numSlots2;
+    sqInt objOop;
+    sqInt oop;
+    sqInt outIndex;
+    usqInt p;
+    sqInt topHashBit;
+    sqInt topOopBit;
+
+	outIndex = 0;
+	/* begin fillObj:numSlots:with: */
+	/* begin numSlotsOf: */
+	flag("endianness");
+	assert((classIndexOf(outPointerArray)) > (isForwardedObjectClassIndexPun()));
+	numSlots2 = byteAt(outPointerArray + 7);
+	numSlots = ((usqInt) ((numSlots2 == 0xFF
+	? longAt(outPointerArray - BaseHeaderSize)
+	: numSlots2)));
+	assert(oopisLessThan(((outPointerArray + BaseHeaderSize) + (numSlots * (bytesPerSlot()))) - 1, addressAfter(outPointerArray)));
+	for (p = (((usqInt)(outPointerArray + BaseHeaderSize))); p <= (((usqInt)(((outPointerArray + BaseHeaderSize) + (numSlots * 4)) - 1))); p += 8) {
+		longAtput(p, GIV(nilObj));
+		longAtput(p + 4, GIV(nilObj));
+	}
+	topHashBit = (((22 - 1) < 0) ? ((usqInt) 1 >> -(22 - 1)) : ((usqInt) 1 << (22 - 1)));
+	topOopBit = ((((BytesPerOop * 8) - 1) < 0) ? ((usqInt) 1 >> -((BytesPerOop * 8) - 1)) : ((usqInt) 1 << ((BytesPerOop * 8) - 1)));
+	/* begin objectStartingAt: */
+	numSlots1 = byteAt(segStart + 7);
+	objOop = (numSlots1 == 0xFF
+		? segStart + BaseHeaderSize
+		: segStart);
+	while (objOop < segAddr) {
+		/* begin fetchClassOfNonImm: */
+		classIndex = (longAt(objOop)) & 0x3FFFFF;
+		if (classIndex <= 0x1F) {
+			if (classIndex == 0x1F) {
+				oop = objOop;
+				goto l1;
+			}
+			if (classIndex == 8) {
+				oop = GIV(nilObj);
+				goto l1;
+			}
+		}
+		assert(classIndex >= (arrayClassIndexPun()));
+		/* begin classOrNilAtIndex: */
+		assert((classIndex <= (tagMask()))
+		 || (classIndex >= (arrayClassIndexPun())));
+		classTablePage = longAt((GIV(hiddenRootsObj) + BaseHeaderSize) + ((((usqInt) classIndex) >> 10) << 2));
+		if (classTablePage == GIV(nilObj)) {
+			oop = GIV(nilObj);
+			goto l2;
+		}
+		oop = longAt((classTablePage + BaseHeaderSize) + ((classIndex & ((1 << 10) - 1)) << 2));
+	l2:	/* end classOrNilAtIndex: */;
+	l1:	/* end fetchClassOfNonImm: */;
+		if (!(((((usqInt) (longAt(oop + 4))) >> 23) & 1) != 0)) {
+
+			/* oop is a new outPointer; allocate its oop */
+
+			/* begin newOutPointer:at:in:hashes:topHashBit: */
+			if (outIndex >= (numSlotsOf(outPointerArray))) {
+
+				/* no room in outPointers; fail */
+
+				outIndex = 0;
+				goto l3;
+			}
+			/* begin storePointer:ofObject:withValue: */
+			assert(!(isForwarded(outPointerArray)));
+			if (isOldObject(outPointerArray)) {
+
+				/* most stores into young objects */
+
+				if (((oop & 3) == 0)
+				 && ((((usqInt) oop)) < (((usqInt) GIV(newSpaceLimit))))) {
+					/* begin possibleRootStoreInto: */
+					if (!(((((usqInt) (longAt(outPointerArray))) >> 29) & 1) != 0)) {
+						remember(outPointerArray);
+					}
+				}
+			}
+			longAtput((outPointerArray + BaseHeaderSize) + (outIndex << 2), oop);
+			long32Atput((savedOutHashes + BaseHeaderSize) + (outIndex << 2), (longAt(oop + 4)) & 0x3FFFFF);
+			/* begin setHashBitsOf:to: */
+			flag("endianness");
+			assert((((outIndex + topHashBit) >= 0) && ((outIndex + topHashBit) <= (identityHashHalfWordMask()))));
+			longAtput(oop + 4, ((((longAt(oop + 4)) | 0x3FFFFF) - 0x3FFFFF)) + (outIndex + topHashBit));
+			setIsMarkedOfto(oop, 1);
+			outIndex += 1;
+		l3:	/* end newOutPointer:at:in:hashes:topHashBit: */;
+			if (outIndex == 0) {
+
+				/* no room in outPointers; fail */
+
+				return -1;
+			}
+		}
+		hash = (longAt(oop + 4)) & 0x3FFFFF;
+		/* begin setClassIndexOf:to: */
+		assert(((hash >= 0) && (hash <= (classIndexMask()))));
+		flag("endianness");
+		longAtput(objOop, ((longAt(objOop)) & (~0x3FFFFF)) + hash);
+		for (i = 0, iLimiT = ((numPointerSlotsOf(objOop)) - 1); i <= iLimiT; i += 1) {
+			oop = longAt((objOop + BaseHeaderSize) + (i << 2));
+			if ((oop & 3) == 0) {
+				if (!(((((usqInt) (longAt(oop + 4))) >> 23) & 1) != 0)) {
+
+					/* oop is a new outPointer; allocate its oop */
+
+					/* begin newOutPointer:at:in:hashes:topHashBit: */
+					if (outIndex >= (numSlotsOf(outPointerArray))) {
+
+						/* no room in outPointers; fail */
+
+						outIndex = 0;
+						goto l4;
+					}
+					/* begin storePointer:ofObject:withValue: */
+					assert(!(isForwarded(outPointerArray)));
+					if (isOldObject(outPointerArray)) {
+
+						/* most stores into young objects */
+
+						if (((oop & 3) == 0)
+						 && ((((usqInt) oop)) < (((usqInt) GIV(newSpaceLimit))))) {
+							/* begin possibleRootStoreInto: */
+							if (!(((((usqInt) (longAt(outPointerArray))) >> 29) & 1) != 0)) {
+								remember(outPointerArray);
+							}
+						}
+					}
+					longAtput((outPointerArray + BaseHeaderSize) + (outIndex << 2), oop);
+					long32Atput((savedOutHashes + BaseHeaderSize) + (outIndex << 2), (longAt(oop + 4)) & 0x3FFFFF);
+					/* begin setHashBitsOf:to: */
+					flag("endianness");
+					assert((((outIndex + topHashBit) >= 0) && ((outIndex + topHashBit) <= (identityHashHalfWordMask()))));
+					longAtput(oop + 4, ((((longAt(oop + 4)) | 0x3FFFFF) - 0x3FFFFF)) + (outIndex + topHashBit));
+					setIsMarkedOfto(oop, 1);
+					outIndex += 1;
+				l4:	/* end newOutPointer:at:in:hashes:topHashBit: */;
+					if (outIndex == 0) {
+
+						/* no room in outPointers; fail */
+
+						return -1;
+					}
+				}
+				/* begin mappedOopOf:topHashBit:topOopBit: */
+				hash1 = (longAt(oop + 4)) & 0x3FFFFF;
+				oop = (hash1 & topHashBit
+					? ((hash1 - topHashBit) * BytesPerOop) + topOopBit
+					: hash1 * 8);
+				/* begin storePointerUnchecked:ofObject:withValue: */
+				assert(!(isForwarded(objOop)));
+				longAtput((objOop + BaseHeaderSize) + (i << 2), oop);
+			}
+		}
+		objOop = objectAfterlimit(objOop, segAddr);
+	}
+	return outIndex;
+}
+
+
 /*	Ensure the class of the argument is marked, pushing it on the markStack if
 	not already marked.
 	Also set the relevant bit in the classTableBitmap so that duplicate
@@ -60514,7 +60737,16 @@
 		assert(numSlots < (numSlotsMask()));
 		byteAtput(objOop + 7, numSlots);
 	}
+
+	/* We have options.
+	   1. we can clone the object and forward to the clone.
+	   2. if the following object has a short header we can given it a large header. */
+
 	delta = bytesBefore - (bytesInObject(objOop));
+	flag("deal with it, dude");
+	if (delta <= 8) {
+		error("shorten:toIndexableSize: attempted to shorten to allocationUnit!");
+	}
 	freeChunk = initFreeChunkWithBytesat(delta, addressAfter(objOop));
 	if (((((usqInt) objOop)) >= (((usqInt) GIV(oldSpaceStart))))
 	 && ((((usqInt) objOop)) < (((usqInt) GIV(endOfMemory))))) {
@@ -60688,13 +60920,16 @@
 	offset in the outPointer array (the first would be 4). but with the high
 	bit set.
 	
+	Since Spur has a class table the load primitive must insert classes that
+	have instances in the class
+	table. This primitive marks such classes using the isRemembered bit, which
+	isn't meaningful as a
+	remembered bit in the segment.
+	
 	The primitive expects the segmentWordArray and outPointerArray to be more
 	than adequately long.
 	In this case it returns normally, and truncates the two arrays to exactly
-	the right size. To simplify
-	truncation, both incoming arrays are required to be whatever the
-	objectMemory considers long
-	objects. If either array is too small, the primitive will fail.
+	the right size.
 	
 	The primitive can fail for the following reasons with the specified
 	failure codes:
@@ -60711,19 +60946,20 @@
     sqInt address1;
     sqInt arrayOfObjects;
     sqInt classIndex;
-    sqInt classIndex1;
     sqInt classTablePage;
-    sqInt classTablePage1;
     sqInt count;
     sqInt endSeg;
     sqInt fillValue;
     sqInt freeChunk;
     sqInt hash;
-    sqInt hash1;
+    sqInt here;
+    sqInt hereLimiT;
     sqInt i;
     sqInt i1;
+    sqInt i2;
     sqInt iLimiT;
     sqInt iLimiT1;
+    sqInt iLimiT2;
     sqInt limit;
     sqInt limit1;
     sqInt newObj;
@@ -60735,22 +60971,21 @@
     sqInt numBytes3;
     sqInt numSlots;
     sqInt numSlots1;
-    usqInt numSlots10;
     usqInt numSlots11;
     usqInt numSlots111;
     usqInt numSlots12;
     usqInt numSlots2;
     usqInt numSlots21;
     sqInt numSlots3;
-    usqInt numSlots4;
-    sqInt numSlots5;
-    sqInt numSlots6;
+    sqInt numSlots4;
+    usqInt numSlots5;
+    usqInt numSlots6;
     usqInt numSlots7;
-    usqInt numSlots8;
-    usqInt numSlots9;
     sqInt obj;
     sqInt objOop;
     sqInt objOop1;
+    sqInt objOop11;
+    sqInt objOop12;
     sqInt objOop2;
     sqInt objOop3;
     sqInt oop;
@@ -60758,7 +60993,6 @@
     sqInt outIndex;
     usqInt p;
     usqInt p1;
-    usqInt p2;
     sqInt prevObj;
     sqInt prevObj1;
     sqInt prevPrevObj;
@@ -60771,21 +61005,9 @@
     sqInt slotBytes;
     sqInt slotBytes1;
     sqInt start;
-    sqInt topHashBit;
-    sqInt topOopBit;
+    sqInt tempObjOop;
+    sqInt there;
 
-	if (!((byteAt(segmentWordArray + 7)) == 0xFF)) {
-
-		/* Must have 128-bit header */
-
-		return PrimErrWritePastObject;
-	}
-	if (!((byteAt(outPointerArray + 7)) == 0xFF)) {
-
-		/* Must have 128-bit header */
-
-		return PrimErrBadIndex;
-	}
 	if ((checkForLeaks & 16) != 0) {
 		/* begin runLeakCheckerForFullGC: */
 		runLeakCheckerForFullGCexcludeUnmarkedNewSpaceObjsclassIndicesShouldBeValid(1, 0, 1);
@@ -60794,7 +61016,20 @@
 	/* begin objectsReachableFromRoots: */
 	assert(isArray(arrayOfRoots));
 	assert(allObjectsUnmarked());
+	/* begin markObjectsIn: */
 	setIsMarkedOfto(arrayOfRoots, 1);
+	for (i1 = 0, iLimiT1 = ((numSlotsOf(arrayOfRoots)) - 1); i1 <= iLimiT1; i1 += 1) {
+		/* begin followField:ofObject: */
+		objOop12 = longAt((arrayOfRoots + BaseHeaderSize) + (i1 << 2));
+		if (((objOop12 & 3) == 0)
+		 && (((longAt(objOop12)) & 0x3FFFFF) == 8)) {
+			objOop12 = fixFollowedFieldofObjectwithInitialValue(i1, arrayOfRoots, objOop12);
+		}
+		oop1 = objOop12;
+		if ((oop1 & 3) == 0) {
+			setIsMarkedOfto(oop1, 1);
+		}
+	}
 	markObjects(0);
 	assert(isEmptyObjStack(GIV(markStack)));
 	assert(isEmptyObjStack(GIV(weaklingStack)));
@@ -60804,18 +61039,28 @@
 	/* begin addressAfter: */
 	/* begin numSlotsOfAny: */
 	numSlots12 = byteAt(freeChunk + 7);
-	numSlots10 = (numSlots12 == 0xFF
+	numSlots7 = (numSlots12 == 0xFF
 		? longAt(freeChunk - BaseHeaderSize)
 		: numSlots12);
-	slotBytes1 = (numSlots10 == 0
+	slotBytes1 = (numSlots7 == 0
 		? 8
-		: (numSlots10 + (numSlots10 & 1)) << 2);
+		: (numSlots7 + (numSlots7 & 1)) << 2);
 	limit = (freeChunk + BaseHeaderSize) + slotBytes1;
 
-	/* First put the roots; order is important. */
+	/* First put the arrayOfRoots; order is important. */
 
 	count = 0;
-	pushonObjStack(arrayOfRoots, GIV(markStack));
+	count += 1;
+	if (ptr < limit) {
+		longAtput(ptr, arrayOfRoots);
+		ptr += 4;
+	}
+	for (i2 = 0, iLimiT2 = ((numSlotsOf(arrayOfRoots)) - 1); i2 <= iLimiT2; i2 += 1) {
+		oop = longAt((arrayOfRoots + BaseHeaderSize) + (i2 << 2));
+		if ((oop & 3) == 0) {
+			pushonObjStack(oop, GIV(markStack));
+		}
+	}
 	while (!(isEmptyObjStack(GIV(markStack)))) {
 		objOop3 = popObjStack(GIV(markStack));
 		count += 1;
@@ -60824,39 +61069,39 @@
 			ptr += 4;
 		}
 		/* begin fetchClassOfNonImm: */
-		classIndex1 = (longAt(objOop3)) & 0x3FFFFF;
-		if (classIndex1 <= 0x1F) {
-			if (classIndex1 == 0x1F) {
-				oop1 = objOop3;
-				goto l7;
+		classIndex = (longAt(objOop3)) & 0x3FFFFF;
+		if (classIndex <= 0x1F) {
+			if (classIndex == 0x1F) {
+				oop = objOop3;
+				goto l3;
 			}
-			if (classIndex1 == 8) {
-				oop1 = GIV(nilObj);
-				goto l7;
+			if (classIndex == 8) {
+				oop = GIV(nilObj);
+				goto l3;
 			}
 		}
-		assert(classIndex1 >= (arrayClassIndexPun()));
+		assert(classIndex >= (arrayClassIndexPun()));
 		/* begin classOrNilAtIndex: */
-		assert((classIndex1 <= (tagMask()))
-		 || (classIndex1 >= (arrayClassIndexPun())));
-		classTablePage1 = longAt((GIV(hiddenRootsObj) + BaseHeaderSize) + ((((usqInt) classIndex1) >> 10) << 2));
-		if (classTablePage1 == GIV(nilObj)) {
-			oop1 = GIV(nilObj);
-			goto l8;
+		assert((classIndex <= (tagMask()))
+		 || (classIndex >= (arrayClassIndexPun())));
+		classTablePage = longAt((GIV(hiddenRootsObj) + BaseHeaderSize) + ((((usqInt) classIndex) >> 10) << 2));
+		if (classTablePage == GIV(nilObj)) {
+			oop = GIV(nilObj);
+			goto l4;
 		}
-		oop1 = longAt((classTablePage1 + BaseHeaderSize) + ((classIndex1 & ((1 << 10) - 1)) << 2));
-	l8:	/* end classOrNilAtIndex: */;
-	l7:	/* end fetchClassOfNonImm: */;
-		if (!(((((usqInt) (longAt(oop1 + 4))) >> 23) & 1) != 0)) {
+		oop = longAt((classTablePage + BaseHeaderSize) + ((classIndex & ((1 << 10) - 1)) << 2));
+	l4:	/* end classOrNilAtIndex: */;
+	l3:	/* end fetchClassOfNonImm: */;
+		if (!(((((usqInt) (longAt(oop + 4))) >> 23) & 1) != 0)) {
 			setIsMarkedOfto(objOop3, 1);
-			pushonObjStack(oop1, GIV(markStack));
+			pushonObjStack(oop, GIV(markStack));
 		}
-		for (i1 = 0, iLimiT1 = ((numPointerSlotsOf(objOop3)) - 1); i1 <= iLimiT1; i1 += 1) {
-			oop1 = longAt((objOop3 + BaseHeaderSize) + (i1 << 2));
-			if (!(((oop1 & 3) != 0)
-				 || (((((usqInt) (longAt(oop1 + 4))) >> 23) & 1) != 0))) {
+		for (i2 = 0, iLimiT2 = ((numPointerSlotsOf(objOop3)) - 1); i2 <= iLimiT2; i2 += 1) {
+			oop = longAt((objOop3 + BaseHeaderSize) + (i2 << 2));
+			if (!(((oop & 3) != 0)
+				 || (((((usqInt) (longAt(oop + 4))) >> 23) & 1) != 0))) {
 				setIsMarkedOfto(objOop3, 1);
-				pushonObjStack(oop1, GIV(markStack));
+				pushonObjStack(oop, GIV(markStack));
 			}
 		}
 	}
@@ -60898,47 +61143,47 @@
 	/* begin objectStartingAt: */
 	address = ((pastSpace()).start);
 	numSlots21 = byteAt(address + 7);
-	objOop1 = (numSlots21 == 0xFF
+	objOop11 = (numSlots21 == 0xFF
 		? address + BaseHeaderSize
 		: address);
 	limit1 = GIV(pastSpaceStart);
-	while ((((usqInt) objOop1)) < (((usqInt) limit1))) {
-		if (((((usqInt) (longAt(objOop1 + 4))) >> 23) & 1) != 0) {
-			if (((longAt(objOop1)) & 0x3FFFFF) > 0x1F) {
-				setIsMarkedOfto(objOop1, 0);
+	while ((((usqInt) objOop11)) < (((usqInt) limit1))) {
+		if (((((usqInt) (longAt(objOop11 + 4))) >> 23) & 1) != 0) {
+			if (((longAt(objOop11)) & 0x3FFFFF) > 0x1F) {
+				setIsMarkedOfto(objOop11, 0);
 			}
 			else {
-				if (!(((longAt(objOop1)) & 0x3FFFFF) == 3)) {
-					setIsMarkedOfto(objOop1, 0);
+				if (!(((longAt(objOop11)) & 0x3FFFFF) == 3)) {
+					setIsMarkedOfto(objOop11, 0);
 				}
 			}
 		}
 
 		prevPrevObj1 = prevObj1;
-		prevObj1 = objOop1;
-		objOop1 = objectAfterlimit(objOop1, limit1);
+		prevObj1 = objOop11;
+		objOop11 = objectAfterlimit(objOop11, limit1);
 	}
 	/* begin objectStartingAt: */
 	address1 = ((eden()).start);
 	numSlots111 = byteAt(address1 + 7);
-	objOop1 = (numSlots111 == 0xFF
+	objOop11 = (numSlots111 == 0xFF
 		? address1 + BaseHeaderSize
 		: address1);
-	while ((((usqInt) objOop1)) < (((usqInt) GIV(freeStart)))) {
-		if (((((usqInt) (longAt(objOop1 + 4))) >> 23) & 1) != 0) {
-			if (((longAt(objOop1)) & 0x3FFFFF) > 0x1F) {
-				setIsMarkedOfto(objOop1, 0);
+	while ((((usqInt) objOop11)) < (((usqInt) GIV(freeStart)))) {
+		if (((((usqInt) (longAt(objOop11 + 4))) >> 23) & 1) != 0) {
+			if (((longAt(objOop11)) & 0x3FFFFF) > 0x1F) {
+				setIsMarkedOfto(objOop11, 0);
 			}
 			else {
-				if (!(((longAt(objOop1)) & 0x3FFFFF) == 3)) {
-					setIsMarkedOfto(objOop1, 0);
+				if (!(((longAt(objOop11)) & 0x3FFFFF) == 3)) {
+					setIsMarkedOfto(objOop11, 0);
 				}
 			}
 		}
 
 		prevPrevObj1 = prevObj1;
-		prevObj1 = objOop1;
-		objOop1 = objectAfterlimit(objOop1, GIV(freeStart));
+		prevObj1 = objOop11;
+		objOop11 = objectAfterlimit(objOop11, GIV(freeStart));
 	}
 	
 	
@@ -60959,7 +61204,7 @@
 		assert(bitsSetInFreeSpaceMaskForAllFreeLists());
 		assert(GIV(totalFreeOldSpace) == (totalFreeListBytes()));
 		arrayOfObjects = ((count << 1) | 1);
-		goto l9;
+		goto l5;
 	}
 	/* begin setFormatOf:to: */
 	assert(((2 >= 0) && (2 <= (formatMask()))));
@@ -60981,24 +61226,25 @@
 	runLeakCheckerForFullGCexcludeUnmarkedNewSpaceObjsclassIndicesShouldBeValid(0, 0, 1);
 	/* return self */
 	arrayOfObjects = freeChunk;
-l9:	/* end objectsReachableFromRoots: */;
+l5:	/* end objectsReachableFromRoots: */;
 	if (!(arrayOfObjects)) {
 		return PrimErrNoMemory;
 	}
+	assert(allObjectsUnmarked());
 	/* begin allocateSlots:format:classIndex: */
 	/* begin numSlotsForBytes: */
 	numBytes2 = (numSlotsOf(arrayOfObjects)) * 4;
-	numSlots5 = (numBytes2 + ((wordSize()) - 1)) / (wordSize());
-	if (numSlots5 >= 0xFF) {
+	numSlots3 = (numBytes2 + ((wordSize()) - 1)) / (wordSize());
+	if (numSlots3 >= 0xFF) {
 		;
 		newObj = GIV(freeStart) + BaseHeaderSize;
-		numBytes = (BaseHeaderSize + BaseHeaderSize) + ((numSlots5 + (numSlots5 & 1)) * 4);
+		numBytes = (BaseHeaderSize + BaseHeaderSize) + ((numSlots3 + (numSlots3 & 1)) * 4);
 	}
 	else {
 		newObj = GIV(freeStart);
-		numBytes = BaseHeaderSize + ((numSlots5 <= 1
+		numBytes = BaseHeaderSize + ((numSlots3 <= 1
 	? 8
-	: (numSlots5 + (numSlots5 & 1)) * 4));
+	: (numSlots3 + (numSlots3 & 1)) * 4));
 	}
 	if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) {
 		if (!GIV(needGCFlag)) {
@@ -61006,40 +61252,40 @@
 			GIV(needGCFlag) = 1;
 			forceInterruptCheck();
 		}
-		savedInHashes = allocateSlotsInOldSpacebytesformatclassIndex(numSlots5, numBytes, 10, 18);
-		goto l3;
+		savedInHashes = allocateSlotsInOldSpacebytesformatclassIndex(numSlots3, numBytes, 10, 18);
+		goto l1;
 	}
-	if (numSlots5 >= 0xFF) {
+	if (numSlots3 >= 0xFF) {
 
 		/* for header parsing we put a saturated slot count in the prepended overflow size word */
 
 		flag("endianness");
-		longAtput(GIV(freeStart), numSlots5);
+		longAtput(GIV(freeStart), numSlots3);
 		longAtput(GIV(freeStart) + 4, 0xFF << 24);
 		long64Atput(newObj, (((((usqLong) 0xFF)) << 56) + (10 << 24)) + 18);
 	}
 	else {
-		long64Atput(newObj, (((((usqLong) numSlots5)) << 56) + (10 << 24)) + 18);
+		long64Atput(newObj, (((((usqLong) numSlots3)) << 56) + (10 << 24)) + 18);
 	}
 	assert((numBytes % (allocationUnit())) == 0);
 	assert((newObj % (allocationUnit())) == 0);
 	GIV(freeStart) += numBytes;
 	savedInHashes = newObj;
-l3:	/* end allocateSlots:format:classIndex: */;
+l1:	/* end allocateSlots:format:classIndex: */;
 	/* begin allocateSlots:format:classIndex: */
 	/* begin numSlotsForBytes: */
 	numBytes3 = (numSlotsOf(outPointerArray)) * 4;
-	numSlots6 = (numBytes3 + ((wordSize()) - 1)) / (wordSize());
-	if (numSlots6 >= 0xFF) {
+	numSlots4 = (numBytes3 + ((wordSize()) - 1)) / (wordSize());
+	if (numSlots4 >= 0xFF) {
 		;
 		newObj1 = GIV(freeStart) + BaseHeaderSize;
-		numBytes1 = (BaseHeaderSize + BaseHeaderSize) + ((numSlots6 + (numSlots6 & 1)) * 4);
+		numBytes1 = (BaseHeaderSize + BaseHeaderSize) + ((numSlots4 + (numSlots4 & 1)) * 4);
 	}
 	else {
 		newObj1 = GIV(freeStart);
-		numBytes1 = BaseHeaderSize + ((numSlots6 <= 1
+		numBytes1 = BaseHeaderSize + ((numSlots4 <= 1
 	? 8
-	: (numSlots6 + (numSlots6 & 1)) * 4));
+	: (numSlots4 + (numSlots4 & 1)) * 4));
 	}
 	if ((GIV(freeStart) + numBytes1) > GIV(scavengeThreshold)) {
 		if (!GIV(needGCFlag)) {
@@ -61047,28 +61293,29 @@
 			GIV(needGCFlag) = 1;
 			forceInterruptCheck();
 		}
-		savedOutHashes = allocateSlotsInOldSpacebytesformatclassIndex(numSlots6, numBytes1, 10, 18);
-		goto l4;
+		savedOutHashes = allocateSlotsInOldSpacebytesformatclassIndex(numSlots4, numBytes1, 10, 18);
+		goto l2;
 	}
-	if (numSlots6 >= 0xFF) {
+	if (numSlots4 >= 0xFF) {
 
 		/* for header parsing we put a saturated slot count in the prepended overflow size word */
 
 		flag("endianness");
-		longAtput(GIV(freeStart), numSlots6);
+		longAtput(GIV(freeStart), numSlots4);
 		longAtput(GIV(freeStart) + 4, 0xFF << 24);
 		long64Atput(newObj1, (((((usqLong) 0xFF)) << 56) + (10 << 24)) + 18);
 	}
 	else {
-		long64Atput(newObj1, (((((usqLong) numSlots6)) << 56) + (10 << 24)) + 18);
+		long64Atput(newObj1, (((((usqLong) numSlots4)) << 56) + (10 << 24)) + 18);
 	}
 	assert((numBytes1 % (allocationUnit())) == 0);
 	assert((newObj1 % (allocationUnit())) == 0);
 	GIV(freeStart) += numBytes1;
 	savedOutHashes = newObj1;
-l4:	/* end allocateSlots:format:classIndex: */;
+l2:	/* end allocateSlots:format:classIndex: */;
 	if ((savedInHashes == null)
 	 || (savedOutHashes == null)) {
+		freeObject(arrayOfObjects);
 		return PrimErrNoMemory;
 	}
 	fillValue = 0x3FFFFF + 1;
@@ -61076,10 +61323,10 @@
 	/* begin numSlotsOf: */
 	flag("endianness");
 	assert((classIndexOf(savedInHashes)) > (isForwardedObjectClassIndexPun()));
-	numSlots7 = byteAt(savedInHashes + 7);
-	numSlots = ((usqInt) ((numSlots7 == 0xFF
+	numSlots5 = byteAt(savedInHashes + 7);
+	numSlots = ((usqInt) ((numSlots5 == 0xFF
 	? longAt(savedInHashes - BaseHeaderSize)
-	: numSlots7)));
+	: numSlots5)));
 	assert(oopisLessThan(((savedInHashes + BaseHeaderSize) + (numSlots * (bytesPerSlot()))) - 1, addressAfter(savedInHashes)));
 	for (p = (((usqInt)(savedInHashes + BaseHeaderSize))); p <= (((usqInt)(((savedInHashes + BaseHeaderSize) + (numSlots * 4)) - 1))); p += 8) {
 		longAtput(p, fillValue);
@@ -61089,15 +61336,45 @@
 	/* begin numSlotsOf: */
 	flag("endianness");
 	assert((classIndexOf(savedOutHashes)) > (isForwardedObjectClassIndexPun()));
-	numSlots8 = byteAt(savedOutHashes + 7);
-	numSlots1 = ((usqInt) ((numSlots8 == 0xFF
+	numSlots6 = byteAt(savedOutHashes + 7);
+	numSlots1 = ((usqInt) ((numSlots6 == 0xFF
 	? longAt(savedOutHashes - BaseHeaderSize)
-	: numSlots8)));
+	: numSlots6)));
 	assert(oopisLessThan(((savedOutHashes + BaseHeaderSize) + (numSlots1 * (bytesPerSlot()))) - 1, addressAfter(savedOutHashes)));
 	for (p1 = (((usqInt)(savedOutHashes + BaseHeaderSize))); p1 <= (((usqInt)(((savedOutHashes + BaseHeaderSize) + (numSlots1 * 4)) - 1))); p1 += 8) {
 		longAtput(p1, fillValue);
 		longAtput(p1 + 4, fillValue);
 	}
+	/* begin moveClassesForwardsIn: */
+
+	/* if > 0, this is the index of the first non-class past the first element. */
+
+	there = 0;
+	for (here = 1, hereLimiT = ((numSlotsOf(arrayOfObjects)) - 1); here <= hereLimiT; here += 1) {
+		objOop1 = longAt((arrayOfObjects + BaseHeaderSize) + (here << 2));
+		hash = (longAt(objOop1 + 4)) & 0x3FFFFF;
+		if ((hash > 0x1F)
+		 && ((classOrNilAtIndex(hash)) == objOop1)) {
+			if (there > 0) {
+
+				/* if there is zero we're in a run of classes at the start so don't move */
+
+				tempObjOop = longAt((arrayOfObjects + BaseHeaderSize) + (there << 2));
+				/* begin storePointerUnchecked:ofObject:withValue: */
+				assert(!(isForwarded(arrayOfObjects)));
+				longAtput((arrayOfObjects + BaseHeaderSize) + (there << 2), objOop1);
+				/* begin storePointerUnchecked:ofObject:withValue: */
+				assert(!(isForwarded(arrayOfObjects)));
+				longAtput((arrayOfObjects + BaseHeaderSize) + (here << 2), tempObjOop);
+				there += 1;
+			}
+		}
+		else {
+			if (there == 0) {
+				there = here;
+			}
+		}
+	}
 	segAddr = segmentWordArray + BaseHeaderSize;
 	/* begin addressAfter: */
 	/* begin numSlotsOfAny: */
@@ -61114,8 +61391,10 @@
 	}
 	long32Atput(segAddr, imageSegmentVersion());
 	long32Atput(segAddr + 4, imageSegmentVersion());
+
+	/* Copy all reachable objects to the segment. */
+
 	segStart = (segAddr += 8);

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list