[Vm-dev] [commit][3054] CogVM source as per VMMaker.oscog-eem.832

commits at squeakvm.org commits at squeakvm.org
Thu Jul 24 08:23:11 UTC 2014


Revision: 3054
Author:   eliot
Date:     2014-07-24 01:23:09 -0700 (Thu, 24 Jul 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.832

Spur:
More rationalization of the class table management post become.  Now no post
become scan of the class table is necessary at all.

Fix bug in assigning parameter 55 (growth ratio at which to do a global GC).

Fix printStringOf: (used in e.g. frame print) to not print crs
that would cause previous info to be overwritten.

Modified Paths:
--------------
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/interp.h
    branches/Cog/nsspursrc/vm/vmCallback.h
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/nsspurstacksrc/vm/interp.h
    branches/Cog/nsspurstacksrc/vm/vmCallback.h
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/interp.h
    branches/Cog/spursistasrc/vm/vmCallback.h
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/interp.h
    branches/Cog/spursrc/vm/vmCallback.h
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.c
    branches/Cog/spurstacksrc/vm/interp.h
    branches/Cog/spurstacksrc/vm/vmCallback.h

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

Modified: branches/Cog/nsspursrc/vm/cointerp.c
===================================================================
--- branches/Cog/nsspursrc/vm/cointerp.c	2014-07-23 12:31:11 UTC (rev 3053)
+++ branches/Cog/nsspursrc/vm/cointerp.c	2014-07-24 08:23:09 UTC (rev 3054)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470
    from
-	CoInterpreter VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9
+	CoInterpreter VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -939,6 +939,7 @@
 static sqInt ephemeronFormat(void);
 static sqInt existInstancesInNewSpaceOf(sqInt classObj) NoDbgRegParms;
 static void expungeDuplicateAndUnmarkedClasses(sqInt expungeUnmarked) NoDbgRegParms;
+static void expungeFromClassTable(sqInt aBehavior) NoDbgRegParms;
 sqInt falseObject(void);
 sqInt fetchByteofObject(sqInt byteIndex, sqInt objOop);
 static sqInt fetchClassOfNonImm(sqInt objOop) NoDbgRegParms;
@@ -1012,6 +1013,7 @@
 sqInt isForwarded(sqInt objOop);
 static sqInt isFreeObject(sqInt objOop) NoDbgRegParms;
 sqInt isImmediate(sqInt oop);
+static sqInt isInClassTable(sqInt objOop) NoDbgRegParms;
 sqInt isIndexable(sqInt objOop);
 static sqInt isInEden(sqInt objOop) NoDbgRegParms;
 static sqInt isInFutureSpace(sqInt address) NoDbgRegParms;
@@ -1073,6 +1075,7 @@
 sqInt nextInSortedFreeListLinkgiven(sqInt freeChunk, sqInt prevFree);
 sqInt nilObject(void);
 static void nilUnmarkedWeaklingSlots(void) NeverInline;
+static sqInt noCheckClassAtIndex(sqInt classIndex) NoDbgRegParms;
 static sqInt noCheckPushonObjStack(sqInt objOop, sqInt objStack) NoDbgRegParms;
 sqInt nonIndexablePointerFormat(void);
 static sqInt noUnscannedEphemerons(void);
@@ -1102,6 +1105,7 @@
 static void printFreeTreeChunk(sqInt chunkOrZero) NoDbgRegParms;
 void printInstancesOf(sqInt aClassOop);
 void printInstancesWithClassIndex(sqInt classIndex);
+void printInvalidClassTableEntries(void);
 void printMethodReferencesTo(sqInt anOop);
 void printObjectsFromto(sqInt startAddress, sqInt endAddress);
 static void printObjStackPagemyIndexpageType(sqInt objStackPage, sqInt myx, sqInt pageType) NoDbgRegParms;
@@ -1140,6 +1144,7 @@
 static sqInt totalFreeListBytes(void);
 sqInt trueObject(void);
 static void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode) NoDbgRegParms;
+static sqInt validClassTableHashes(void);
 static sqInt validClassTableRootPages(void);
 static sqInt validObjStacks(void);
 sqInt vmEndianness(void);
@@ -1370,7 +1375,7 @@
 void printStackPages(void);
 void printStackPagesInUse(void);
 static void printStackPage(StackPage *page) NoDbgRegParms;
-static sqInt printStringOf(sqInt oop) NoDbgRegParms;
+static void printStringOf(sqInt oop) NoDbgRegParms;
 void print(char *s);
 void pushBool(sqInt trueOrFalse);
 static sqInt pushedReceiverOrClosureOfFrame(char *theFP) NoDbgRegParms;
@@ -1524,18 +1529,18 @@
 _iss StackPage * mostRecentlyUsedPage;
 _iss sqInt numStackPages;
 _iss SpurNewSpaceSpace pastSpace;
+_iss sqInt classTableFirstPage;
 _iss usqInt newSpaceStart;
-_iss sqInt classTableFirstPage;
 _iss usqInt oldSpaceStart;
 _iss sqInt markStack;
 _iss sqInt profileProcess;
 _iss SpurNewSpaceSpace futureSpace;
 _iss sqInt longRunningPrimitiveCheckSemaphore;
+_iss sqInt numClassTablePages;
 _iss sqInt numRememberedEphemerons;
 _iss sqInt profileSemaphore;
 _iss sqInt jmpDepth;
 _iss sqLong nextProfileTick;
-_iss sqInt numClassTablePages;
 _iss sqInt profileMethod;
 _iss sqInt classNameIndex;
 _iss sqInt futureSurvivorStart;
@@ -1547,12 +1552,12 @@
 _iss sqInt ephemeronList;
 _iss usqInt freeOldSpaceStart;
 _iss sqInt tenureThreshold;
+_iss sqInt classTableIndex;
 _iss sqInt extraRootCount;
 _iss sqInt invalidObjStackPage;
 _iss sqInt previousRememberedSetSize;
 _iss unsigned char * classTableBitmap;
 _iss sqInt growHeadroom;
-_iss sqInt classTableIndex;
 _iss sqInt ephemeronQueue;
 _iss sqInt lastMethodCacheProbeWrite;
 _iss sqInt metaclassNumSlots;
@@ -1561,7 +1566,6 @@
 _iss sqInt lkupClass;
 _iss usqLong nextWakeupUsecs;
 _iss sqInt numSegInfos;
-_iss sqInt becomeEffectsFlags;
 _iss sqInt highestRunnableProcessPriority;
 _iss sqInt lastCoggableInterpretedBlockMethod;
 _iss sqInt lastUncoggableInterpretedBlockMethod;
@@ -1571,6 +1575,7 @@
 _iss usqLong statCheckForEvents;
 _iss usqLong statGCEndUsecs;
 _iss sqInt weakList;
+_iss sqInt becomeEffectsFlags;
 _iss sqInt cogCodeSize;
 _iss sqInt externalPrimitiveTableFirstFreeIndex;
 _iss sqInt flagInterpretedMethods;
@@ -2311,7 +2316,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 CoInterpreter_VMMaker.oscog-eem.831";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.832";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -41939,7 +41944,6 @@
 becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt c;
-    sqInt classOrNil;
     sqInt classTablePage;
     sqInt clone1;
     sqInt clone2;
@@ -41954,7 +41958,6 @@
     sqInt fmt;
     sqInt fmt1;
     sqInt fmt2;
-    sqInt hashBits;
     sqInt headerPointer;
     sqInt headerPointer1;
     sqLong headerTemp;
@@ -41964,14 +41967,11 @@
     sqInt i2;
     sqInt i3;
     sqInt i4;
-    sqInt i5;
     sqInt iLimiT;
     sqInt iLimiT1;
     sqInt iLimiT2;
     sqInt iLimiT3;
     sqInt iLimiT4;
-    sqInt j;
-    sqInt jLimiT;
     sqInt last;
     sqInt list;
     sqInt m;
@@ -41983,8 +41983,10 @@
     sqInt numLiterals;
     sqInt numLiterals1;
     sqInt o1ClassIndex;
+    sqInt o1HashBits;
     sqInt o1HasYoung;
     sqInt o2ClassIndex;
+    sqInt o2HashBits;
     sqInt o2HasYoung;
     sqInt obj;
     sqInt obj1;
@@ -42010,7 +42012,6 @@
     sqInt objOop9;
     sqInt oop;
     sqInt oop1;
-    sqInt page;
     sqInt procLists;
     sqInt referent;
     sqInt referent1;
@@ -42024,7 +42025,6 @@
     sqInt referent4;
     sqInt referent41;
     sqInt referent5;
-    sqInt referent51;
     sqInt referent6;
     sqInt referent7;
     sqInt referent8;
@@ -42076,14 +42076,14 @@
 				contextSize = (sp >> 1);
 			l2:	/* end fetchStackPointerOf: */;
 				fieldOffset = (CtxtTempFrameStart + contextSize) * BytesPerOop;
-				goto l3;
+				goto l1;
 			}
 			fieldOffset = (((numSlotsOf(array1)) - 1) * BytesPerOop) + (BaseHeaderSize);
-			goto l3;
+			goto l1;
 		}
 		if (fmt < 24) {
 			fieldOffset = 0;
-			goto l3;
+			goto l1;
 		}
 		/* begin literalCountOfHeader: */
 		/* begin headerOf: */
@@ -42096,7 +42096,7 @@
 						? (((usqInt) headerPointer) >> 1) & 0xFFFF
 						: (((usqInt) headerPointer) >> 10) & 0xFF);
 		fieldOffset = (((numLiterals + LiteralStart) - 1) * BytesPerOop) + (BaseHeaderSize);
-	l3:	/* end lastPointerOf: */;
+	l1:	/* end lastPointerOf: */;
 
 		/* same size as array2 */
 
@@ -42105,7 +42105,7 @@
 			oop = longAt(array1 + fieldOffset);
 			if ((oop & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l4;
+				goto l3;
 			}
 			if (((longAt(oop)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42120,13 +42120,13 @@
 			}
 			if (((((usqInt) (longAt(oop))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l4;
+				goto l3;
 			}
 			effectsFlags = effectsFlags | (becomeEffectFlagsFor(oop));
 			oop = longAt(array2 + fieldOffset);
 			if ((oop & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l4;
+				goto l3;
 			}
 			if (((longAt(oop)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42141,14 +42141,14 @@
 			}
 			if (((((usqInt) (longAt(oop))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l4;
+				goto l3;
 			}
 			effectsFlags = effectsFlags | (becomeEffectFlagsFor(oop));
 			fieldOffset -= BytesPerOop;
 		}
 		GIV(becomeEffectsFlags) = effectsFlags;
 		ec = 0;
-	l4:	/* end containsOnlyValidBecomeObjects:and: */;
+	l3:	/* end containsOnlyValidBecomeObjects:and: */;
 	}
 	else {
 		followForwardedObjectFieldstoDepth(array2, 0);
@@ -42166,20 +42166,20 @@
 				sp1 = longAt((array1 + (BaseHeaderSize)) + (StackPointerIndex << 2));
 				if (!((sp1 & 1))) {
 					contextSize1 = 0;
-					goto l6;
+					goto l5;
 				}
 				assert((ReceiverIndex + ((sp1 >> 1))) < (lengthOf(array1)));
 				contextSize1 = (sp1 >> 1);
-			l6:	/* end fetchStackPointerOf: */;
+			l5:	/* end fetchStackPointerOf: */;
 				fieldOffset1 = (CtxtTempFrameStart + contextSize1) * BytesPerOop;
-				goto l5;
+				goto l4;
 			}
 			fieldOffset1 = (((numSlotsOf(array1)) - 1) * BytesPerOop) + (BaseHeaderSize);
-			goto l5;
+			goto l4;
 		}
 		if (fmt1 < 24) {
 			fieldOffset1 = 0;
-			goto l5;
+			goto l4;
 		}
 		/* begin literalCountOfHeader: */
 		/* begin headerOf: */
@@ -42192,7 +42192,7 @@
 						? (((usqInt) headerPointer1) >> 1) & 0xFFFF
 						: (((usqInt) headerPointer1) >> 10) & 0xFF);
 		fieldOffset1 = (((numLiterals1 + LiteralStart) - 1) * BytesPerOop) + (BaseHeaderSize);
-	l5:	/* end lastPointerOf: */;
+	l4:	/* end lastPointerOf: */;
 
 		/* same size as array2 */
 
@@ -42201,7 +42201,7 @@
 			oop1 = longAt(array1 + fieldOffset1);
 			if ((oop1 & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l7;
+				goto l6;
 			}
 			if (((longAt(oop1)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42216,14 +42216,14 @@
 			}
 			if (((((usqInt) (longAt(oop1))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l7;
+				goto l6;
 			}
 			effectsFlags1 = effectsFlags1 | (becomeEffectFlagsFor(oop1));
 			fieldOffset1 -= BytesPerOop;
 		}
 		GIV(becomeEffectsFlags) = effectsFlags1;
 		ec = 0;
-	l7:	/* end containsOnlyValidBecomeObjects: */;
+	l6:	/* end containsOnlyValidBecomeObjects: */;
 	}
 	if (ec != 0) {
 		return ec;
@@ -42250,7 +42250,7 @@
 
 			/* At first blush it would appear unnecessary to use followField: here since
 			   the validation in become:with:twoWay:copyHash: follows forwarders.  But
-			   there's nothing to ensure all elements of each array is unique and doesn't
+			   there's nothing to ensure all elements of each array are unique and don't
 			   appear in the other array.  So the enumeration could encounter an object
 			   already becommed earlier in the same enumeration. */
 
@@ -42317,15 +42317,15 @@
 						longAtput(obj2 + 4, ((((longAt(obj2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + temp1);
 					}
 					o1HasYoung = (o2HasYoung = 0);
-					for (i5 = 0, iLimiT4 = ((numSlotsOf(obj1)) - 1); i5 <= iLimiT4; i5 += 1) {
-						temp1 = longAt((obj1 + (BaseHeaderSize)) + (i5 << 2));
-						temp2 = longAt((obj2 + (BaseHeaderSize)) + (i5 << 2));
+					for (i4 = 0, iLimiT4 = ((numSlotsOf(obj1)) - 1); i4 <= iLimiT4; i4 += 1) {
+						temp1 = longAt((obj1 + (BaseHeaderSize)) + (i4 << 2));
+						temp2 = longAt((obj2 + (BaseHeaderSize)) + (i4 << 2));
 						/* begin storePointerUnchecked:ofObject:withValue: */
 						assert(!(isForwarded(obj1)));
-						longAtput((obj1 + (BaseHeaderSize)) + (i5 << 2), temp2);
+						longAtput((obj1 + (BaseHeaderSize)) + (i4 << 2), temp2);
 						/* begin storePointerUnchecked:ofObject:withValue: */
 						assert(!(isForwarded(obj2)));
-						longAtput((obj2 + (BaseHeaderSize)) + (i5 << 2), temp1);
+						longAtput((obj2 + (BaseHeaderSize)) + (i4 << 2), temp1);
 						if (((temp2 & 3) == 0)
 						 && ((((usqInt) temp2)) < (((usqInt) GIV(newSpaceLimit))))) {
 							o1HasYoung = 1;
@@ -42357,92 +42357,95 @@
 							}
 						}
 					}
+					assert((o1ClassIndex == 0)
+					 || ((rawHashBitsOf(classAtIndex(o1ClassIndex))) == o1ClassIndex));
+					assert((o2ClassIndex == 0)
+					 || ((rawHashBitsOf(classAtIndex(o2ClassIndex))) == o2ClassIndex));
+					goto l8;
 				}
+				/* begin outOfPlaceBecome:and:copyHashFlag: */
+				clone1 = (((longAt(obj1)) & 0x3FFFFF) == ClassMethodContextCompactIndex
+					? cloneContext(obj1)
+					: clone(obj1));
+				clone2 = (((longAt(obj2)) & 0x3FFFFF) == ClassMethodContextCompactIndex
+					? cloneContext(obj2)
+					: clone(obj2));
+				if (copyHashFlag) {
+					/* begin setHashBitsOf:to: */
+					flag("endianness");
+					assert(((((longAt(obj2 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj2 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
+					longAtput(clone1 + 4, ((((longAt(clone1 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj2 + 4)) & 0x3FFFFF));
+					/* begin setHashBitsOf:to: */
+					flag("endianness");
+					assert(((((longAt(obj1 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj1 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
+					longAtput(clone2 + 4, ((((longAt(clone2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj1 + 4)) & 0x3FFFFF));
+				}
 				else {
-					/* begin outOfPlaceBecome:and:copyHashFlag: */
-					clone1 = (((longAt(obj1)) & 0x3FFFFF) == ClassMethodContextCompactIndex
-						? cloneContext(obj1)
-						: clone(obj1));
-					clone2 = (((longAt(obj2)) & 0x3FFFFF) == ClassMethodContextCompactIndex
-						? cloneContext(obj2)
-						: clone(obj2));
-					if (copyHashFlag) {
-						/* begin setHashBitsOf:to: */
-						flag("endianness");
-						assert(((((longAt(obj2 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj2 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
-						longAtput(clone1 + 4, ((((longAt(clone1 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj2 + 4)) & 0x3FFFFF));
-						/* begin setHashBitsOf:to: */
-						flag("endianness");
-						assert(((((longAt(obj1 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj1 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
-						longAtput(clone2 + 4, ((((longAt(clone2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj1 + 4)) & 0x3FFFFF));
-					}
-					else {
-						/* begin setHashBitsOf:to: */
-						flag("endianness");
-						assert(((((longAt(obj1 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj1 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
-						longAtput(clone1 + 4, ((((longAt(clone1 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj1 + 4)) & 0x3FFFFF));
-						/* begin setHashBitsOf:to: */
-						flag("endianness");
-						assert(((((longAt(obj2 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj2 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
-						longAtput(clone2 + 4, ((((longAt(clone2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj2 + 4)) & 0x3FFFFF));
-					}
-					/* begin forward:to: */
-					/* begin set:classIndexTo:formatTo: */
-					assert(((8 >= 0) && (8 <= (classIndexMask()))));
-					assert(((7 >= 0) && (7 <= (formatMask()))));
+					/* begin setHashBitsOf:to: */
 					flag("endianness");
-					longAtput(obj1, ((longAt(obj1)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
-					/* begin storePointer:ofForwarder:withValue: */
-					assert(isForwarded(obj1));
-					assert(!(isOopForwarded(clone2)));
-					if (isOldObject(obj1)) {
+					assert(((((longAt(obj1 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj1 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
+					longAtput(clone1 + 4, ((((longAt(clone1 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj1 + 4)) & 0x3FFFFF));
+					/* begin setHashBitsOf:to: */
+					flag("endianness");
+					assert(((((longAt(obj2 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj2 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
+					longAtput(clone2 + 4, ((((longAt(clone2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj2 + 4)) & 0x3FFFFF));
+				}
+				/* begin forward:to: */
+				/* begin set:classIndexTo:formatTo: */
+				assert(((8 >= 0) && (8 <= (classIndexMask()))));
+				assert(((7 >= 0) && (7 <= (formatMask()))));
+				flag("endianness");
+				longAtput(obj1, ((longAt(obj1)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
+				/* begin storePointer:ofForwarder:withValue: */
+				assert(isForwarded(obj1));
+				assert(!(isOopForwarded(clone2)));
+				if (isOldObject(obj1)) {
 
-						/* most stores into young objects */
+					/* most stores into young objects */
 
-						if (((clone2 & 3) == 0)
-						 && ((((usqInt) clone2)) < (((usqInt) GIV(newSpaceLimit))))) {
-							/* begin possibleRootStoreInto: */
-							if (!(((((usqInt) (longAt(obj1))) >> 29) & 1) != 0)) {
-								remember(obj1);
-							}
+					if (((clone2 & 3) == 0)
+					 && ((((usqInt) clone2)) < (((usqInt) GIV(newSpaceLimit))))) {
+						/* begin possibleRootStoreInto: */
+						if (!(((((usqInt) (longAt(obj1))) >> 29) & 1) != 0)) {
+							remember(obj1);
 						}
 					}
-					longAtput((obj1 + (BaseHeaderSize)) + (0 << 2), clone2);
-					if ((byteAt(obj1 + 7)) == 0) {
-						/* begin setRawNumSlotsOf:to: */
-						flag("endian");
-						byteAtput(obj1 + 7, 1);
-					}
-					/* begin forward:to: */
-					/* begin set:classIndexTo:formatTo: */
-					assert(((8 >= 0) && (8 <= (classIndexMask()))));
-					assert(((7 >= 0) && (7 <= (formatMask()))));
-					flag("endianness");
-					longAtput(obj2, ((longAt(obj2)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
-					/* begin storePointer:ofForwarder:withValue: */
-					assert(isForwarded(obj2));
-					assert(!(isOopForwarded(clone1)));
-					if (isOldObject(obj2)) {
+				}
+				longAtput((obj1 + (BaseHeaderSize)) + (0 << 2), clone2);
+				if ((byteAt(obj1 + 7)) == 0) {
+					/* begin setRawNumSlotsOf:to: */
+					flag("endian");
+					byteAtput(obj1 + 7, 1);
+				}
+				/* begin forward:to: */
+				/* begin set:classIndexTo:formatTo: */
+				assert(((8 >= 0) && (8 <= (classIndexMask()))));
+				assert(((7 >= 0) && (7 <= (formatMask()))));
+				flag("endianness");
+				longAtput(obj2, ((longAt(obj2)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
+				/* begin storePointer:ofForwarder:withValue: */
+				assert(isForwarded(obj2));
+				assert(!(isOopForwarded(clone1)));
+				if (isOldObject(obj2)) {
 
-						/* most stores into young objects */
+					/* most stores into young objects */
 
-						if (((clone1 & 3) == 0)
-						 && ((((usqInt) clone1)) < (((usqInt) GIV(newSpaceLimit))))) {
-							/* begin possibleRootStoreInto: */
-							if (!(((((usqInt) (longAt(obj2))) >> 29) & 1) != 0)) {
-								remember(obj2);
-							}
+					if (((clone1 & 3) == 0)
+					 && ((((usqInt) clone1)) < (((usqInt) GIV(newSpaceLimit))))) {
+						/* begin possibleRootStoreInto: */
+						if (!(((((usqInt) (longAt(obj2))) >> 29) & 1) != 0)) {
+							remember(obj2);
 						}
 					}
-					longAtput((obj2 + (BaseHeaderSize)) + (0 << 2), clone1);
-					if ((byteAt(obj2 + 7)) == 0) {
-						/* begin setRawNumSlotsOf:to: */
-						flag("endian");
-						byteAtput(obj2 + 7, 1);
-					}
 				}
+				longAtput((obj2 + (BaseHeaderSize)) + (0 << 2), clone1);
+				if ((byteAt(obj2 + 7)) == 0) {
+					/* begin setRawNumSlotsOf:to: */
+					flag("endian");
+					byteAtput(obj2 + 7, 1);
+				}
 				if (copyHashFlag) {
-					goto l9;
+					goto l8;
 				}
 				if (o1ClassIndex != 0) {
 					if (o2ClassIndex != 0) {
@@ -42455,10 +42458,10 @@
 						classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + ((((usqInt) o1ClassIndex) >> 10) << 2));
 						if (classTablePage == GIV(nilObj)) {
 							tmp = null;
-							goto l8;
+							goto l7;
 						}
 						tmp = longAt((classTablePage + (BaseHeaderSize)) + ((o1ClassIndex & ((1 << 10) - 1)) << 2));
-					l8:	/* end classAtIndex: */;
+					l7:	/* end classAtIndex: */;
 						classAtIndexput(o1ClassIndex, obj2);
 						classAtIndexput(o2ClassIndex, tmp);
 					}
@@ -42466,19 +42469,14 @@
 
 						/* o2 wasn't in the table; put it there */
 
-						if (((longAt(obj1)) & (0x3FFFFF - 8)) == 0) {
-							/* begin followForwarded: */
-							assert(isUnambiguouslyForwarder(obj1));
-							referent9 = longAt((obj1 + (BaseHeaderSize)) + (0 << 2));
-							while (((referent9 & 3) == 0)
-							 && (((longAt(referent9)) & 0x3FFFFF) == 8)) {
-								referent9 = longAt((referent9 + (BaseHeaderSize)) + (0 << 2));
-							}
-							newObj2 = referent9;
+						/* begin followForwarded: */
+						assert(isUnambiguouslyForwarder(obj1));
+						referent9 = longAt((obj1 + (BaseHeaderSize)) + (0 << 2));
+						while (((referent9 & 3) == 0)
+						 && (((longAt(referent9)) & 0x3FFFFF) == 8)) {
+							referent9 = longAt((referent9 + (BaseHeaderSize)) + (0 << 2));
 						}
-						else {
-							newObj2 = obj1;
-						}
+						newObj2 = referent9;
 						assert((rawHashBitsOf(newObj2)) == 0);
 						/* begin setHashBitsOf:to: */
 						flag("endianness");
@@ -42489,19 +42487,14 @@
 				}
 				else {
 					if (o2ClassIndex != 0) {
-						if (((longAt(obj2)) & (0x3FFFFF - 8)) == 0) {
-							/* begin followForwarded: */
-							assert(isUnambiguouslyForwarder(obj2));
-							referent13 = longAt((obj2 + (BaseHeaderSize)) + (0 << 2));
-							while (((referent13 & 3) == 0)
-							 && (((longAt(referent13)) & 0x3FFFFF) == 8)) {
-								referent13 = longAt((referent13 + (BaseHeaderSize)) + (0 << 2));
-							}
-							newObj1 = referent13;
+						/* begin followForwarded: */
+						assert(isUnambiguouslyForwarder(obj2));
+						referent13 = longAt((obj2 + (BaseHeaderSize)) + (0 << 2));
+						while (((referent13 & 3) == 0)
+						 && (((longAt(referent13)) & 0x3FFFFF) == 8)) {
+							referent13 = longAt((referent13 + (BaseHeaderSize)) + (0 << 2));
 						}
-						else {
-							newObj1 = obj2;
-						}
+						newObj1 = referent13;
 						assert((rawHashBitsOf(newObj1)) == 0);
 						/* begin setHashBitsOf:to: */
 						flag("endianness");
@@ -42510,7 +42503,7 @@
 						classAtIndexput(o2ClassIndex, newObj1);
 					}
 				}
-			l9:	/* end doBecome:and:copyHash: */;
+			l8:	/* end doBecome:and:copyHash: */;
 				/* begin followField:ofObject: */
 				objOop = longAt((array1 + (BaseHeaderSize)) + (i << 2));
 				if (((objOop & 3) == 0)
@@ -42554,6 +42547,8 @@
 			obj21 = objOop6;
 			if (obj11 != obj21) {
 				/* begin doBecome:to:copyHash: */
+				o1HashBits = (longAt(obj11 + 4)) & 0x3FFFFF;
+				o2HashBits = (longAt(obj21 + 4)) & 0x3FFFFF;
 				/* begin forward:to: */
 				/* begin set:classIndexTo:formatTo: */
 				assert(((8 >= 0) && (8 <= (classIndexMask()))));
@@ -42582,17 +42577,30 @@
 					byteAtput(obj11 + 7, 1);
 				}
 				if (copyHashFlag) {
+					/* begin setHashBitsOf:to: */
+					flag("endianness");
+					assert(((o1HashBits >= 0) && (o1HashBits <= (identityHashHalfWordMask()))));
+					longAtput(obj21 + 4, ((((longAt(obj21 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + o1HashBits);
+				}
+				if ((o1HashBits != 0)
+				 && ((classAtIndex(o1HashBits)) == obj11)) {
+					expungeFromClassTable(obj11);
+				}
+				else {
+					o1HashBits = 0;
+				}
+				assert(!((isForwarded(obj21))));
+				if (o1HashBits != 0) {
+					if (o2HashBits == 0) {
 
-					/* silently refuse to change the hash of classes; this shouldn't happen anyway. */
+						/* obj2 has no hash; we're free to assign one */
 
-					hashBits = (longAt(obj21 + 4)) & 0x3FFFFF;
-					if ((classAtIndex(hashBits)) != obj21) {
-						hashBits = (longAt(obj11 + 4)) & 0x3FFFFF;
 						/* begin setHashBitsOf:to: */
 						flag("endianness");
-						assert(((hashBits >= 0) && (hashBits <= (identityHashHalfWordMask()))));
-						longAtput(obj21 + 4, ((((longAt(obj21 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + hashBits);
+						assert(((o1HashBits >= 0) && (o1HashBits <= (identityHashHalfWordMask()))));
+						longAtput(obj21 + 4, ((((longAt(obj21 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + o1HashBits);
 					}
+					classAtIndexput(o1HashBits, obj21);
 				}
 				/* begin followField:ofObject: */
 				objOop4 = longAt((array1 + (BaseHeaderSize)) + (i1 << 2));
@@ -42609,63 +42617,23 @@
 	if (((longAt(GIV(specialObjectsOop))) & (0x3FFFFF - 8)) == 0) {
 		/* begin followForwarded: */
 		assert(isUnambiguouslyForwarder(GIV(specialObjectsOop)));
-		referent5 = longAt((GIV(specialObjectsOop) + (BaseHeaderSize)) + (0 << 2));
-		while (((referent5 & 3) == 0)
-		 && (((longAt(referent5)) & 0x3FFFFF) == 8)) {
-			referent5 = longAt((referent5 + (BaseHeaderSize)) + (0 << 2));
+		referent4 = longAt((GIV(specialObjectsOop) + (BaseHeaderSize)) + (0 << 2));
+		while (((referent4 & 3) == 0)
+		 && (((longAt(referent4)) & 0x3FFFFF) == 8)) {
+			referent4 = longAt((referent4 + (BaseHeaderSize)) + (0 << 2));
 		}
-		GIV(specialObjectsOop) = referent5;
+		GIV(specialObjectsOop) = referent4;
 	}
 	followForwardedObjectFieldstoDepth(GIV(specialObjectsOop), 0);
-	/* begin postBecomeOrCompactScanClassTable: */
-	assert(validClassTableRootPages());
-	if (!(GIV(becomeEffectsFlags) & BecamePointerObjectFlag)) {
-		goto l1;
-	}
-	for (i2 = 0; i2 < GIV(numClassTablePages); i2 += 1) {
-		page = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i2 << 2));
-		assert(!(isForwarded(page)));
-		for (j = 0, jLimiT = ((numSlotsOf(page)) - 1); j <= jLimiT; j += 1) {
-			classOrNil = longAt((page + (BaseHeaderSize)) + (j << 2));
-			if (classOrNil != GIV(nilObj)) {
-				if (((longAt(classOrNil)) & (0x3FFFFF - 8)) == 0) {
-					/* begin followForwarded: */
-					assert(isUnambiguouslyForwarder(classOrNil));
-					referent = longAt((classOrNil + (BaseHeaderSize)) + (0 << 2));
-					while (((referent & 3) == 0)
-					 && (((longAt(referent)) & 0x3FFFFF) == 8)) {
-						referent = longAt((referent + (BaseHeaderSize)) + (0 << 2));
-					}
-					classOrNil = referent;
-					/* begin storePointer:ofObject:withValue: */
-					assert(!(isForwarded(page)));
-					if (isOldObject(page)) {
-
-						/* most stores into young objects */
-
-						if (((classOrNil & 3) == 0)
-						 && ((((usqInt) classOrNil)) < (((usqInt) GIV(newSpaceLimit))))) {
-							/* begin possibleRootStoreInto: */
-							if (!(((((usqInt) (longAt(page))) >> 29) & 1) != 0)) {
-								remember(page);
-							}
-						}
-					}
-					longAtput((page + (BaseHeaderSize)) + (j << 2), classOrNil);
-				}
-			}
-		}
-	}
-l1:	/* end postBecomeOrCompactScanClassTable: */;
 	/* begin postBecomeAction: */
 	followForwardingPointersInStackZone(GIV(becomeEffectsFlags));
 	if (GIV(becomeEffectsFlags) != 0) {
 		if (GIV(becomeEffectsFlags) & BecameCompiledMethodFlag) {
 			/* begin followForwardedMethodsInMethodCache */
-			for (i3 = 0; i3 < MethodCacheSize; i3 += MethodCacheEntrySize) {
-				c = GIV(methodCache)[i3 + MethodCacheClass];
-				s = GIV(methodCache)[i3 + MethodCacheSelector];
-				m = GIV(methodCache)[i3 + MethodCacheMethod];
+			for (i2 = 0; i2 < MethodCacheSize; i2 += MethodCacheEntrySize) {
+				c = GIV(methodCache)[i2 + MethodCacheClass];
+				s = GIV(methodCache)[i2 + MethodCacheSelector];
+				m = GIV(methodCache)[i2 + MethodCacheMethod];
 				if ((c != 0)
 				 && ((s != 0)
 				 && ((m != 0)
@@ -42673,13 +42641,13 @@
 				 && (((longAt(m)) & 0x3FFFFF) == 8))))) {
 					/* begin followForwarded: */
 					assert(isUnambiguouslyForwarder(m));
-					referent1 = longAt((m + (BaseHeaderSize)) + (0 << 2));
-					while (((referent1 & 3) == 0)
-					 && (((longAt(referent1)) & 0x3FFFFF) == 8)) {
-						referent1 = longAt((referent1 + (BaseHeaderSize)) + (0 << 2));
+					referent = longAt((m + (BaseHeaderSize)) + (0 << 2));
+					while (((referent & 3) == 0)
+					 && (((longAt(referent)) & 0x3FFFFF) == 8)) {
+						referent = longAt((referent + (BaseHeaderSize)) + (0 << 2));
 					}
-					m = referent1;
-					GIV(methodCache)[i3 + MethodCacheMethod] = m;
+					m = referent;
+					GIV(methodCache)[i2 + MethodCacheMethod] = m;
 				}
 			}
 			/* begin followForwardedMethodsInMethodZone */
@@ -42874,18 +42842,18 @@
 			}
 			longAtput((GIV(specialObjectsOop) + (BaseHeaderSize)) + (ExternalObjectsArray << 2), xArray);
 		}
-		for (i4 = 0, iLimiT3 = ((numSlotsOf(xArray)) - 1); i4 <= iLimiT3; i4 += 1) {
+		for (i3 = 0, iLimiT3 = ((numSlotsOf(xArray)) - 1); i3 <= iLimiT3; i3 += 1) {
 			/* begin followSemaphoreIn:at: */
-			obj = longAt((xArray + (BaseHeaderSize)) + (i4 << 2));
+			obj = longAt((xArray + (BaseHeaderSize)) + (i3 << 2));
 			if (((longAt(obj)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
 				assert(isUnambiguouslyForwarder(obj));
-				referent51 = longAt((obj + (BaseHeaderSize)) + (0 << 2));
-				while (((referent51 & 3) == 0)
-				 && (((longAt(referent51)) & 0x3FFFFF) == 8)) {
-					referent51 = longAt((referent51 + (BaseHeaderSize)) + (0 << 2));
+				referent5 = longAt((obj + (BaseHeaderSize)) + (0 << 2));
+				while (((referent5 & 3) == 0)
+				 && (((longAt(referent5)) & 0x3FFFFF) == 8)) {
+					referent5 = longAt((referent5 + (BaseHeaderSize)) + (0 << 2));
 				}
-				obj = referent51;
+				obj = referent5;
 				/* begin storePointer:ofObject:withValue: */
 				assert(!(isForwarded(xArray)));
 				if (isOldObject(xArray)) {
@@ -42900,45 +42868,46 @@
 						}
 					}
 				}
-				longAtput((xArray + (BaseHeaderSize)) + (i4 << 2), obj);
+				longAtput((xArray + (BaseHeaderSize)) + (i3 << 2), obj);
 			}
 		}
 		/* begin followForwardingPointersInProfileState */
 		if (((longAt(GIV(profileProcess))) & (0x3FFFFF - 8)) == 0) {
 			/* begin followForwarded: */
 			assert(isUnambiguouslyForwarder(GIV(profileProcess)));
-			referent2 = longAt((GIV(profileProcess) + (BaseHeaderSize)) + (0 << 2));
-			while (((referent2 & 3) == 0)
-			 && (((longAt(referent2)) & 0x3FFFFF) == 8)) {
-				referent2 = longAt((referent2 + (BaseHeaderSize)) + (0 << 2));
+			referent1 = longAt((GIV(profileProcess) + (BaseHeaderSize)) + (0 << 2));
+			while (((referent1 & 3) == 0)
+			 && (((longAt(referent1)) & 0x3FFFFF) == 8)) {
+				referent1 = longAt((referent1 + (BaseHeaderSize)) + (0 << 2));
 			}
-			GIV(profileProcess) = referent2;
+			GIV(profileProcess) = referent1;
 		}
 		if (((longAt(GIV(profileMethod))) & (0x3FFFFF - 8)) == 0) {
 			/* begin followForwarded: */
 			assert(isUnambiguouslyForwarder(GIV(profileMethod)));
-			referent3 = longAt((GIV(profileMethod) + (BaseHeaderSize)) + (0 << 2));
-			while (((referent3 & 3) == 0)
-			 && (((longAt(referent3)) & 0x3FFFFF) == 8)) {
-				referent3 = longAt((referent3 + (BaseHeaderSize)) + (0 << 2));
+			referent2 = longAt((GIV(profileMethod) + (BaseHeaderSize)) + (0 << 2));
+			while (((referent2 & 3) == 0)
+			 && (((longAt(referent2)) & 0x3FFFFF) == 8)) {
+				referent2 = longAt((referent2 + (BaseHeaderSize)) + (0 << 2));
 			}
-			GIV(profileMethod) = referent3;
+			GIV(profileMethod) = referent2;
 		}
 		if (((longAt(GIV(profileProcess))) & (0x3FFFFF - 8)) == 0) {
 			/* begin followForwarded: */
 			assert(isUnambiguouslyForwarder(GIV(profileSemaphore)));
-			referent4 = longAt((GIV(profileSemaphore) + (BaseHeaderSize)) + (0 << 2));
-			while (((referent4 & 3) == 0)
-			 && (((longAt(referent4)) & 0x3FFFFF) == 8)) {
-				referent4 = longAt((referent4 + (BaseHeaderSize)) + (0 << 2));
+			referent3 = longAt((GIV(profileSemaphore) + (BaseHeaderSize)) + (0 << 2));
+			while (((referent3 & 3) == 0)
+			 && (((longAt(referent3)) & 0x3FFFFF) == 8)) {
+				referent3 = longAt((referent3 + (BaseHeaderSize)) + (0 << 2));
 			}
-			GIV(profileSemaphore) = referent4;
+			GIV(profileSemaphore) = referent3;
 		}
 	}
 	cogitPostGCAction(GIV(gcMode));
 	GIV(lastCoggableInterpretedBlockMethod) = (GIV(lastUncoggableInterpretedBlockMethod) = null);
 	GIV(gcMode) = 0;
 	GIV(becomeEffectsFlags) = 0;
+	assert(validClassTableHashes());
 	if ((checkForLeaks & 4) != 0) {
 		/* begin runLeakCheckerForFullGC: */
 		runLeakCheckerForFullGCexcludeUnmarkedNewSpaceObjsclassIndicesShouldBeValid(1, 0, 1);
@@ -43805,7 +43774,8 @@
 	assert((classIndex <= (tagMask()))
 	 || (classIndex >= (arrayClassIndexPun())));
 	assert((objOop == GIV(nilObj))
-	 || (((rawHashBitsOf(objOop)) == classIndex)
+	 || ((((rawHashBitsOf(objOop)) == classIndex)
+	 || ((classAtIndex(rawHashBitsOf(objOop))) == objOop))
 	 && (objCouldBeClassObj(objOop))));
 	classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + ((((usqInt) classIndex) >> 10) << 2));
 	if (classTablePage == GIV(nilObj)) {
@@ -45376,6 +45346,33 @@
 	}
 }
 
+
+/*	Remove aBehavior from the class table. */
+
+static void
+expungeFromClassTable(sqInt aBehavior)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classIndex;
+    sqInt classTablePage;
+    sqInt majorIndex;
+    sqInt minorIndex;
+
+	assert(isInClassTable(aBehavior));
+	classIndex = (longAt(aBehavior + 4)) & 0x3FFFFF;
+	majorIndex = ((usqInt) classIndex) >> 10;
+	minorIndex = classIndex & ((1 << 10) - 1);
+	classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (majorIndex << 2));
+	assert(classTablePage != GIV(classTableFirstPage));
+	assert((numSlotsOf(classTablePage)) == (classTablePageSize()));
+	assert((fetchPointerofObject(minorIndex, classTablePage)) == aBehavior);
+	/* begin storePointerUnchecked:ofObject:withValue: */
+	assert(!(isForwarded(classTablePage)));
+	longAtput((classTablePage + (BaseHeaderSize)) + (minorIndex << 2), GIV(nilObj));
+	if (classIndex < GIV(classTableIndex)) {
+		GIV(classTableIndex) = classIndex;
+	}
+}
+
 sqInt
 falseObject(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
@@ -47416,6 +47413,16 @@
 	return (oop & 3) != 0;
 }
 
+static sqInt
+isInClassTable(sqInt objOop)
+{
+    sqInt hash;
+
+	hash = (longAt(objOop + 4)) & 0x3FFFFF;
+	return (hash != 0)
+	 && ((classAtIndex(hash)) == objOop);
+}
+
 sqInt
 isIndexable(sqInt objOop)
 {
@@ -49613,7 +49620,19 @@
 	emptyObjStack(GIV(weaklingStack));
 }
 
+static sqInt
+noCheckClassAtIndex(sqInt classIndex)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classTablePage;
 
+	classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + ((((usqInt) classIndex) >> 10) << 2));
+	if (classTablePage == GIV(nilObj)) {
+		return null;
+	}
+	return longAt((classTablePage + (BaseHeaderSize)) + ((classIndex & ((1 << 10) - 1)) << 2));
+}
+
+
 /*	Push an element on an objStack. Split from push:onObjStack: for testing. */
 
 static sqInt
@@ -50792,6 +50811,49 @@
 }
 
 
+/*	Print the objects in the classTable that have bad hashes. */
+
+void
+printInvalidClassTableEntries(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classOrNil;
+    sqInt hash;
+    sqInt i;
+    sqInt j;
+    sqInt jLimiT;
+    sqInt page;
+
+	if (!(validClassTableRootPages())) {
+		print("class table invalid; cannot print");
+		/* begin cr */
+		printf("\n");
+		return;
+	}
+	for (i = 0; i < GIV(numClassTablePages); i += 1) {
+		page = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i << 2));
+		for (j = 0, jLimiT = ((1 << 10) - 1); j <= jLimiT; j += 1) {
+			classOrNil = longAt((page + (BaseHeaderSize)) + (j << 2));
+			if (classOrNil != GIV(nilObj)) {
+				if ((((longAt(classOrNil)) & (0x3FFFFF - 8)) == 0)
+				 || ((((hash = (longAt(classOrNil + 4)) & 0x3FFFFF)) == 0)
+				 || ((noCheckClassAtIndex(hash)) != classOrNil))) {
+					print("entry ");
+					printHex((i * (1 << 10)) + j);
+					print(" oop ");
+					printHex(classOrNil);
+					print(" hash ");
+					printHex(hash);
+					print(" => ");
+					printHex(classAtIndex(hash));
+					/* begin cr */
+					printf("\n");
+				}
+			}
+		}
+	}
+}
+
+
 /*	Scan the heap printing the oops of any and all methods that refer to anOop */
 
 void
@@ -52204,6 +52266,46 @@
 }
 
 
+/*	Check the hashes of classes in the table. The tricky thing here is that
+	classes may be duplicated
+	in the table. So each entry ,ust be in the table at its hash, even if it
+	is elsewhere in the table. */
+
+static sqInt
+validClassTableHashes(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classOrNil;
+    sqInt hash;
+    sqInt i;
+    sqInt j;
+    sqInt jLimiT;
+    sqInt page;
+
+	if (!(validClassTableRootPages())) {
+		return 0;
+	}
+	for (i = 0; i < GIV(numClassTablePages); i += 1) {
+		page = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i << 2));
+		for (j = 0, jLimiT = ((1 << 10) - 1); j <= jLimiT; j += 1) {
+			classOrNil = longAt((page + (BaseHeaderSize)) + (j << 2));
+			if (classOrNil != GIV(nilObj)) {
+				if (((longAt(classOrNil)) & (0x3FFFFF - 8)) == 0) {
+					return 0;
+				}
+				hash = (longAt(classOrNil + 4)) & 0x3FFFFF;
+				if (hash == 0) {
+					return 0;
+				}
+				if ((noCheckClassAtIndex(hash)) != classOrNil) {
+					return 0;
+				}
+			}
+		}
+	}
+	return 1;
+}
+
+
 /*	Answer if hiddenRootsObj is of the right size with the
 	expected contents, and if numClassTablePages is correct. */
 
@@ -58735,17 +58837,15 @@
 	 && (((fieldOop = longAt((objOop + (BaseHeaderSize)) + (SuperclassIndex << 2))),
 	(((fieldOop & 3) == 0)
 		 && ((((((usqInt) (longAt(fieldOop))) >> 24) & 0x1F) <= 5)
-		 || ((((longAt(fieldOop + 4)) & 0x3FFFFF) == 0)
-		 && ((((fieldOop & 3) == 0)
+		 || ((((fieldOop & 3) == 0)
 		 && (((longAt(fieldOop)) & 0x3FFFFF) == 8))
-		 && (isPointers(followForwarded(fieldOop)))))))
+		 && (isPointers(followForwarded(fieldOop))))))
 		 && (((fieldOop = longAt((objOop + (BaseHeaderSize)) + (MethodDictionaryIndex << 2))),
 		(((fieldOop & 3) == 0)
 			 && ((((((usqInt) (longAt(fieldOop))) >> 24) & 0x1F) <= 5)
-			 || ((((longAt(fieldOop + 4)) & 0x3FFFFF) == 0)
-			 && ((((fieldOop & 3) == 0)
+			 || ((((fieldOop & 3) == 0)
 			 && (((longAt(fieldOop)) & 0x3FFFFF) == 8))
-			 && (isPointers(followForwarded(fieldOop)))))))
+			 && (isPointers(followForwarded(fieldOop))))))
 			 && (((longAt((objOop + (BaseHeaderSize)) + (InstanceSpecificationIndex << 2))) & 1)))))));
 }
 
@@ -61235,7 +61335,7 @@
 	printf("\n");
 }
 
-static sqInt
+static void
 printStringOf(sqInt oop)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt cnt;
@@ -61245,14 +61345,14 @@
     sqInt max;
 
 	if ((oop & 3) != 0) {
-		return null;
+		return;
 	}
 	if (!(addressCouldBeObj(oop))) {
-		return null;
+		return;
 	}
 	fmt = (((usqInt) (longAt(oop))) >> 24) & 0x1F;
 	if (fmt < 16) {
-		return null;
+		return;
 	}
 	cnt = ((((max = 128)) < ((len = lengthOfformat(oop, (((usqInt) (longAt(oop))) >> 24) & 0x1F)))) ? ((max = 128)) : ((len = lengthOfformat(oop, (((usqInt) (longAt(oop))) >> 24) & 0x1F))));
 	i = 0;
@@ -61266,6 +61366,16 @@
 	}
 	else {
 		while (i < cnt) {
+			if ((byteAt((oop + (BaseHeaderSize)) + i)) == 13) {
+
+				/* Character cr asInteger */
+
+				print("<CR>");
+				if ((i + 1) < len) {
+					print("...");
+				}
+				return;
+			}
 			/* begin printChar: */
 			putchar(byteAt((oop + (BaseHeaderSize)) + i));
 			i += 1;
@@ -67687,6 +67797,7 @@
 		aDouble = 0.0;
 	l3:	/* end floatValueOf: */;
 		GIV(heapGrowthToSizeGCRatio) = aDouble;
+		GIV(primFailCode) = 0;
 	}
 	if (!GIV(primFailCode)) {
 		/* begin pop:thenPush: */

Modified: branches/Cog/nsspursrc/vm/cointerp.h
===================================================================
--- branches/Cog/nsspursrc/vm/cointerp.h	2014-07-23 12:31:11 UTC (rev 3053)
+++ branches/Cog/nsspursrc/vm/cointerp.h	2014-07-24 08:23:09 UTC (rev 3054)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470
  */
 
 
@@ -230,6 +230,7 @@
 void printFreeTree(void);
 void printInstancesOf(sqInt aClassOop);
 void printInstancesWithClassIndex(sqInt classIndex);
+void printInvalidClassTableEntries(void);
 void printMethodReferencesTo(sqInt anOop);
 void printObjectsFromto(sqInt startAddress, sqInt endAddress);
 void printObjStack(sqInt objStack);

Modified: branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nsspursrc/vm/gcc3x-cointerp.c	2014-07-23 12:31:11 UTC (rev 3053)
+++ branches/Cog/nsspursrc/vm/gcc3x-cointerp.c	2014-07-24 08:23:09 UTC (rev 3054)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470
    from
-	CoInterpreter VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9
+	CoInterpreter VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.831 uuid: c231d214-1763-4c79-9b58-a5bf3385b0c9 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.832 uuid: afcb9ff1-804f-4aae-b052-a709b5a26470 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -942,6 +942,7 @@
 static sqInt ephemeronFormat(void);
 static sqInt existInstancesInNewSpaceOf(sqInt classObj) NoDbgRegParms;
 static void expungeDuplicateAndUnmarkedClasses(sqInt expungeUnmarked) NoDbgRegParms;
+static void expungeFromClassTable(sqInt aBehavior) NoDbgRegParms;
 sqInt falseObject(void);
 sqInt fetchByteofObject(sqInt byteIndex, sqInt objOop);
 static sqInt fetchClassOfNonImm(sqInt objOop) NoDbgRegParms;
@@ -1015,6 +1016,7 @@
 sqInt isForwarded(sqInt objOop);
 static sqInt isFreeObject(sqInt objOop) NoDbgRegParms;
 sqInt isImmediate(sqInt oop);
+static sqInt isInClassTable(sqInt objOop) NoDbgRegParms;
 sqInt isIndexable(sqInt objOop);
 static sqInt isInEden(sqInt objOop) NoDbgRegParms;
 static sqInt isInFutureSpace(sqInt address) NoDbgRegParms;
@@ -1076,6 +1078,7 @@
 sqInt nextInSortedFreeListLinkgiven(sqInt freeChunk, sqInt prevFree);
 sqInt nilObject(void);
 static void nilUnmarkedWeaklingSlots(void) NeverInline;
+static sqInt noCheckClassAtIndex(sqInt classIndex) NoDbgRegParms;
 static sqInt noCheckPushonObjStack(sqInt objOop, sqInt objStack) NoDbgRegParms;
 sqInt nonIndexablePointerFormat(void);
 static sqInt noUnscannedEphemerons(void);
@@ -1105,6 +1108,7 @@
 static void printFreeTreeChunk(sqInt chunkOrZero) NoDbgRegParms;
 void printInstancesOf(sqInt aClassOop);
 void printInstancesWithClassIndex(sqInt classIndex);
+void printInvalidClassTableEntries(void);
 void printMethodReferencesTo(sqInt anOop);
 void printObjectsFromto(sqInt startAddress, sqInt endAddress);
 static void printObjStackPagemyIndexpageType(sqInt objStackPage, sqInt myx, sqInt pageType) NoDbgRegParms;
@@ -1143,6 +1147,7 @@
 static sqInt totalFreeListBytes(void);
 sqInt trueObject(void);
 static void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode) NoDbgRegParms;
+static sqInt validClassTableHashes(void);
 static sqInt validClassTableRootPages(void);
 static sqInt validObjStacks(void);
 sqInt vmEndianness(void);
@@ -1373,7 +1378,7 @@
 void printStackPages(void);
 void printStackPagesInUse(void);
 static void printStackPage(StackPage *page) NoDbgRegParms;
-static sqInt printStringOf(sqInt oop) NoDbgRegParms;
+static void printStringOf(sqInt oop) NoDbgRegParms;
 void print(char *s);
 void pushBool(sqInt trueOrFalse);
 static sqInt pushedReceiverOrClosureOfFrame(char *theFP) NoDbgRegParms;
@@ -1527,18 +1532,18 @@
 _iss StackPage * mostRecentlyUsedPage;
 _iss sqInt numStackPages;
 _iss SpurNewSpaceSpace pastSpace;
+_iss sqInt classTableFirstPage;
 _iss usqInt newSpaceStart;
-_iss sqInt classTableFirstPage;
 _iss usqInt oldSpaceStart;
 _iss sqInt markStack;
 _iss sqInt profileProcess;
 _iss SpurNewSpaceSpace futureSpace;
 _iss sqInt longRunningPrimitiveCheckSemaphore;
+_iss sqInt numClassTablePages;
 _iss sqInt numRememberedEphemerons;
 _iss sqInt profileSemaphore;
 _iss sqInt jmpDepth;
 _iss sqLong nextProfileTick;
-_iss sqInt numClassTablePages;
 _iss sqInt profileMethod;
 _iss sqInt classNameIndex;
 _iss sqInt futureSurvivorStart;
@@ -1550,12 +1555,12 @@
 _iss sqInt ephemeronList;
 _iss usqInt freeOldSpaceStart;
 _iss sqInt tenureThreshold;
+_iss sqInt classTableIndex;
 _iss sqInt extraRootCount;
 _iss sqInt invalidObjStackPage;
 _iss sqInt previousRememberedSetSize;
 _iss unsigned char * classTableBitmap;
 _iss sqInt growHeadroom;
-_iss sqInt classTableIndex;
 _iss sqInt ephemeronQueue;
 _iss sqInt lastMethodCacheProbeWrite;
 _iss sqInt metaclassNumSlots;
@@ -1564,7 +1569,6 @@
 _iss sqInt lkupClass;
 _iss usqLong nextWakeupUsecs;
 _iss sqInt numSegInfos;
-_iss sqInt becomeEffectsFlags;
 _iss sqInt highestRunnableProcessPriority;
 _iss sqInt lastCoggableInterpretedBlockMethod;
 _iss sqInt lastUncoggableInterpretedBlockMethod;
@@ -1574,6 +1578,7 @@
 _iss usqLong statCheckForEvents;
 _iss usqLong statGCEndUsecs;
 _iss sqInt weakList;
+_iss sqInt becomeEffectsFlags;
 _iss sqInt cogCodeSize;
 _iss sqInt externalPrimitiveTableFirstFreeIndex;
 _iss sqInt flagInterpretedMethods;
@@ -2314,7 +2319,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 CoInterpreter_VMMaker.oscog-eem.831";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.832";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -41948,7 +41953,6 @@
 becomewithtwoWaycopyHash(sqInt array1, sqInt array2, sqInt twoWayFlag, sqInt copyHashFlag)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt c;
-    sqInt classOrNil;
     sqInt classTablePage;
     sqInt clone1;
     sqInt clone2;
@@ -41963,7 +41967,6 @@
     sqInt fmt;
     sqInt fmt1;
     sqInt fmt2;
-    sqInt hashBits;
     sqInt headerPointer;
     sqInt headerPointer1;
     sqLong headerTemp;
@@ -41973,14 +41976,11 @@
     sqInt i2;
     sqInt i3;
     sqInt i4;
-    sqInt i5;
     sqInt iLimiT;
     sqInt iLimiT1;
     sqInt iLimiT2;
     sqInt iLimiT3;
     sqInt iLimiT4;
-    sqInt j;
-    sqInt jLimiT;
     sqInt last;
     sqInt list;
     sqInt m;
@@ -41992,8 +41992,10 @@
     sqInt numLiterals;
     sqInt numLiterals1;
     sqInt o1ClassIndex;
+    sqInt o1HashBits;
     sqInt o1HasYoung;
     sqInt o2ClassIndex;
+    sqInt o2HashBits;
     sqInt o2HasYoung;
     sqInt obj;
     sqInt obj1;
@@ -42019,7 +42021,6 @@
     sqInt objOop9;
     sqInt oop;
     sqInt oop1;
-    sqInt page;
     sqInt procLists;
     sqInt referent;
     sqInt referent1;
@@ -42033,7 +42034,6 @@
     sqInt referent4;
     sqInt referent41;
     sqInt referent5;
-    sqInt referent51;
     sqInt referent6;
     sqInt referent7;
     sqInt referent8;
@@ -42085,14 +42085,14 @@
 				contextSize = (sp >> 1);
 			l2:	/* end fetchStackPointerOf: */;
 				fieldOffset = (CtxtTempFrameStart + contextSize) * BytesPerOop;
-				goto l3;
+				goto l1;
 			}
 			fieldOffset = (((numSlotsOf(array1)) - 1) * BytesPerOop) + (BaseHeaderSize);
-			goto l3;
+			goto l1;
 		}
 		if (fmt < 24) {
 			fieldOffset = 0;
-			goto l3;
+			goto l1;
 		}
 		/* begin literalCountOfHeader: */
 		/* begin headerOf: */
@@ -42105,7 +42105,7 @@
 						? (((usqInt) headerPointer) >> 1) & 0xFFFF
 						: (((usqInt) headerPointer) >> 10) & 0xFF);
 		fieldOffset = (((numLiterals + LiteralStart) - 1) * BytesPerOop) + (BaseHeaderSize);
-	l3:	/* end lastPointerOf: */;
+	l1:	/* end lastPointerOf: */;
 
 		/* same size as array2 */
 
@@ -42114,7 +42114,7 @@
 			oop = longAt(array1 + fieldOffset);
 			if ((oop & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l4;
+				goto l3;
 			}
 			if (((longAt(oop)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42129,13 +42129,13 @@
 			}
 			if (((((usqInt) (longAt(oop))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l4;
+				goto l3;
 			}
 			effectsFlags = effectsFlags | (becomeEffectFlagsFor(oop));
 			oop = longAt(array2 + fieldOffset);
 			if ((oop & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l4;
+				goto l3;
 			}
 			if (((longAt(oop)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42150,14 +42150,14 @@
 			}
 			if (((((usqInt) (longAt(oop))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l4;
+				goto l3;
 			}
 			effectsFlags = effectsFlags | (becomeEffectFlagsFor(oop));
 			fieldOffset -= BytesPerOop;
 		}
 		GIV(becomeEffectsFlags) = effectsFlags;
 		ec = 0;
-	l4:	/* end containsOnlyValidBecomeObjects:and: */;
+	l3:	/* end containsOnlyValidBecomeObjects:and: */;
 	}
 	else {
 		followForwardedObjectFieldstoDepth(array2, 0);
@@ -42175,20 +42175,20 @@
 				sp1 = longAt((array1 + (BaseHeaderSize)) + (StackPointerIndex << 2));
 				if (!((sp1 & 1))) {
 					contextSize1 = 0;
-					goto l6;
+					goto l5;
 				}
 				assert((ReceiverIndex + ((sp1 >> 1))) < (lengthOf(array1)));
 				contextSize1 = (sp1 >> 1);
-			l6:	/* end fetchStackPointerOf: */;
+			l5:	/* end fetchStackPointerOf: */;
 				fieldOffset1 = (CtxtTempFrameStart + contextSize1) * BytesPerOop;
-				goto l5;
+				goto l4;
 			}
 			fieldOffset1 = (((numSlotsOf(array1)) - 1) * BytesPerOop) + (BaseHeaderSize);
-			goto l5;
+			goto l4;
 		}
 		if (fmt1 < 24) {
 			fieldOffset1 = 0;
-			goto l5;
+			goto l4;
 		}
 		/* begin literalCountOfHeader: */
 		/* begin headerOf: */
@@ -42201,7 +42201,7 @@
 						? (((usqInt) headerPointer1) >> 1) & 0xFFFF
 						: (((usqInt) headerPointer1) >> 10) & 0xFF);
 		fieldOffset1 = (((numLiterals1 + LiteralStart) - 1) * BytesPerOop) + (BaseHeaderSize);
-	l5:	/* end lastPointerOf: */;
+	l4:	/* end lastPointerOf: */;
 
 		/* same size as array2 */
 
@@ -42210,7 +42210,7 @@
 			oop1 = longAt(array1 + fieldOffset1);
 			if ((oop1 & 3) != 0) {
 				ec = PrimErrInappropriate;
-				goto l7;
+				goto l6;
 			}
 			if (((longAt(oop1)) & (0x3FFFFF - 8)) == 0) {
 				/* begin followForwarded: */
@@ -42225,14 +42225,14 @@
 			}
 			if (((((usqInt) (longAt(oop1))) >> 30) & 1) != 0) {
 				ec = PrimErrObjectIsPinned;
-				goto l7;
+				goto l6;
 			}
 			effectsFlags1 = effectsFlags1 | (becomeEffectFlagsFor(oop1));
 			fieldOffset1 -= BytesPerOop;
 		}
 		GIV(becomeEffectsFlags) = effectsFlags1;
 		ec = 0;
-	l7:	/* end containsOnlyValidBecomeObjects: */;
+	l6:	/* end containsOnlyValidBecomeObjects: */;
 	}
 	if (ec != 0) {
 		return ec;
@@ -42259,7 +42259,7 @@
 
 			/* At first blush it would appear unnecessary to use followField: here since
 			   the validation in become:with:twoWay:copyHash: follows forwarders.  But
-			   there's nothing to ensure all elements of each array is unique and doesn't
+			   there's nothing to ensure all elements of each array are unique and don't
 			   appear in the other array.  So the enumeration could encounter an object
 			   already becommed earlier in the same enumeration. */
 
@@ -42326,15 +42326,15 @@
 						longAtput(obj2 + 4, ((((longAt(obj2 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + temp1);
 					}
 					o1HasYoung = (o2HasYoung = 0);
-					for (i5 = 0, iLimiT4 = ((numSlotsOf(obj1)) - 1); i5 <= iLimiT4; i5 += 1) {
-						temp1 = longAt((obj1 + (BaseHeaderSize)) + (i5 << 2));
-						temp2 = longAt((obj2 + (BaseHeaderSize)) + (i5 << 2));
+					for (i4 = 0, iLimiT4 = ((numSlotsOf(obj1)) - 1); i4 <= iLimiT4; i4 += 1) {
+						temp1 = longAt((obj1 + (BaseHeaderSize)) + (i4 << 2));
+						temp2 = longAt((obj2 + (BaseHeaderSize)) + (i4 << 2));
 						/* begin storePointerUnchecked:ofObject:withValue: */
 						assert(!(isForwarded(obj1)));
-						longAtput((obj1 + (BaseHeaderSize)) + (i5 << 2), temp2);
+						longAtput((obj1 + (BaseHeaderSize)) + (i4 << 2), temp2);
 						/* begin storePointerUnchecked:ofObject:withValue: */
 						assert(!(isForwarded(obj2)));
-						longAtput((obj2 + (BaseHeaderSize)) + (i5 << 2), temp1);
+						longAtput((obj2 + (BaseHeaderSize)) + (i4 << 2), temp1);
 						if (((temp2 & 3) == 0)
 						 && ((((usqInt) temp2)) < (((usqInt) GIV(newSpaceLimit))))) {
 							o1HasYoung = 1;
@@ -42366,92 +42366,95 @@
 							}
 						}
 					}
+					assert((o1ClassIndex == 0)
+					 || ((rawHashBitsOf(classAtIndex(o1ClassIndex))) == o1ClassIndex));
+					assert((o2ClassIndex == 0)

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list