[Vm-dev] [commit][3093] CogVM source as per VMMaker.oscog-eem.890

commits at squeakvm.org commits at squeakvm.org
Fri Oct 3 16:45:18 UTC 2014


Revision: 3093
Author:   eliot
Date:     2014-10-03 09:45:17 -0700 (Fri, 03 Oct 2014)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.890

Spur:
Fix one-way become for classes with and without copyHash, primarily by fixing
allInstances.  One-way become for classes causes duplicates in the class table
(either that or an allInstances scan would be needed as part of the become to
change instances referring to the deleted class index, which would be slow).
So allInstances must be able to cope with duplicates.  Hence split it into a
fast path common case when the class in question is not duplicated, and a slower
path when it is.  Make both the marking phase of GC and allInstances check for
and eliminate refereces to duplicate entries at wrong/obsolete class indices.

Fix markAndShouldScan: to not scan the pun classes of non-objects on the heap
such as implicit receiver caches and Sista counters.

Eliminate the classTableBitmap premature optimization.  All the information we
need is in the cassTable and the class's hashes therein.

Change pinObject: to answer 0 on failure and the (possibly moved) object on
success.  Much easier than having to check and follow forwarding pointer.
The changes to platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c
in r3092 in a Spur MT VM depend on this.

Fix some C compilation warnings

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

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

Modified: branches/Cog/nsspursrc/vm/cogit.c
===================================================================
--- branches/Cog/nsspursrc/vm/cogit.c	2014-10-03 16:44:41 UTC (rev 3092)
+++ branches/Cog/nsspursrc/vm/cogit.c	2014-10-03 16:45:17 UTC (rev 3093)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.889 uuid: f7ca0f83-4116-4c07-8307-3c23f8f5600a
+	CCodeGenerator VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.889 uuid: f7ca0f83-4116-4c07-8307-3c23f8f5600a
+	StackToRegisterMappingCogit VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.889 uuid: f7ca0f83-4116-4c07-8307-3c23f8f5600a " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703 " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -14039,7 +14039,7 @@
 
 			/* It's a linked send, but maybe a super send or linked to an OpenPIC, in which case the cache tag will be a selector.... */
 
-			if (isForwardedClassIndex(inlineCacheTagAt(backEnd, mcpc))) {
+			if (isForwardedClassIndex(inlineCacheTagAt(backEnd, ((sqInt)mcpc)))) {
 				/* begin targetMethodAndSendTableFor:into: */
 				if ((entryPoint & entryPointMask) == checkedEntryAlignment) {
 					targetMethod1 = ((CogMethod *) (entryPoint - cmEntryOffset));

Modified: branches/Cog/nsspursrc/vm/cogit.h
===================================================================
--- branches/Cog/nsspursrc/vm/cogit.h	2014-10-03 16:44:41 UTC (rev 3092)
+++ branches/Cog/nsspursrc/vm/cogit.h	2014-10-03 16:45:17 UTC (rev 3093)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.889 uuid: f7ca0f83-4116-4c07-8307-3c23f8f5600a
+	CCodeGenerator VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703
  */
 
 

Modified: branches/Cog/nsspursrc/vm/cointerp.c
===================================================================
--- branches/Cog/nsspursrc/vm/cointerp.c	2014-10-03 16:44:41 UTC (rev 3092)
+++ branches/Cog/nsspursrc/vm/cointerp.c	2014-10-03 16:45:17 UTC (rev 3093)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.887 uuid: f980d45a-5622-46f6-95d9-ac8d00a34e81
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703
    from
-	CoInterpreter VMMaker.oscog-eem.887 uuid: f980d45a-5622-46f6-95d9-ac8d00a34e81
+	CoInterpreter VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.887 uuid: f980d45a-5622-46f6-95d9-ac8d00a34e81 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.890 uuid: 4cec861e-a7df-45b3-8298-ecb127ee6703 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -867,6 +867,7 @@
 static sqInt allObjects(void);
 static sqInt allObjectsUnmarked(void);
 static sqInt allOldMarkedWeakObjectsOnWeaklingStack(void);
+static sqInt allocateLargestFreeChunk(void);
 static sqInt allocateNewSpaceSlotsformatclassIndex(sqInt numSlots, sqInt formatField, sqInt classIndex) NoDbgRegParms;
 static sqInt allocateOldSpaceChunkOfBytes(usqInt chunkBytes) NoDbgRegParms;
 sqInt allocatePinnedSlots(sqInt nSlots);
@@ -936,14 +937,11 @@
 sqInt eeInstantiateClassIndexformatnumSlots(sqInt knownClassIndex, sqInt objFormat, sqInt numSlots);
 static void eliminateAndFreeForwardersForPigCompact(void);
 static void emptyObjStack(sqInt objStack) NoDbgRegParms;
-static void ensureAdequateClassTableBitmap(void);
 static sqInt ensureBehaviorHash(sqInt aBehavior) NoDbgRegParms;
 static sqInt ensureRoomOnObjStackAt(sqInt objStackRootIndex) NoDbgRegParms;
 static sqInt enterIntoClassTable(sqInt aBehavior) NoDbgRegParms;
 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;
@@ -956,7 +954,6 @@
 void findString(char *aCString);
 static sqInt firstAccessibleObject(void);
 sqInt firstByteFormat(void);
-static sqInt firstClassIndexPun(void);
 sqInt firstCompiledMethodFormat(void);
 static void * firstFixedFieldOfMaybeImmediate(sqInt oop) NoDbgRegParms;
 void * firstFixedField(sqInt objOop);
@@ -1005,6 +1002,7 @@
 sqInt isBytes(sqInt oop);
 sqInt isCharacterObject(sqInt oop);
 sqInt isCharacterValue(sqInt anInteger);
+static sqInt isClassAtUniqueIndex(sqInt aClass) NoDbgRegParms;
 static sqInt isCompiledMethodHeader(sqInt objHeader) NoDbgRegParms;
 sqInt isCompiledMethod(sqInt objOop);
 static sqInt isContextHeader(sqInt aHeader) NoDbgRegParms;
@@ -1019,7 +1017,6 @@
 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;
@@ -1517,8 +1514,8 @@
 _iss char * stackBasePlus1;
 _iss usqInt endOfMemory;
 _iss SpurSegmentInfo * segments;
-_iss sqInt needGCFlag;
 _iss sqInt trueObj;
+_iss sqInt needGCFlag;
 _iss sqInt falseObj;
 _iss sqInt remapBufferCount;
 _iss usqInt newSpaceStart;
@@ -1541,10 +1538,10 @@
 _iss sqInt numStackPages;
 _iss SpurNewSpaceSpace pastSpace;
 _iss sqInt classTableFirstPage;
-_iss usqInt oldSpaceStart;
 _iss sqInt markStack;
 _iss sqInt numClassTablePages;
 _iss sqInt profileProcess;
+_iss usqInt oldSpaceStart;
 _iss SpurNewSpaceSpace futureSpace;
 _iss sqInt longRunningPrimitiveCheckSemaphore;
 _iss sqInt numRememberedEphemerons;
@@ -1567,7 +1564,6 @@
 _iss sqInt extraRootCount;
 _iss sqInt invalidObjStackPage;
 _iss sqInt previousRememberedSetSize;
-_iss unsigned char * classTableBitmap;
 _iss sqInt growHeadroom;
 _iss sqInt ephemeronQueue;
 _iss sqInt lastMethodCacheProbeWrite;
@@ -2305,7 +2301,7 @@
 /*120*/	-1, 1,-1,-1, 0,-1, 0, 0, 0,-1,-1,-1, 1, 0, 0,-1, 0,-1,-1, 0,
 /*140*/	-1, 1,-1, 1, 0, 0,-1,-1, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
 /*160*/	0, 0,-1,-1,-1, 1, 1,-1, 1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,
-/*180*/	0,-1,-1, 0, 1, 0, 1, 1, 1, 0,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,
+/*180*/	0,-1,-1, 0, 0, 0, 1, 1, 1, 0,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,
 /*200*/	-1, 2, 2, 2, 2, 2, 2,-1,-1,-1, 1, 1, 1, 1,-1, 1,-1,-1, 3,-1,
 /*220*/	-1, 2, 2,-1,-1,-1,-1,-1,-1,-1, 0,-1, 2, 0,-1,-1,-1,-1,-1,-1,
 /*240*/	-1,-1, 0,-1,-1,-1,-1,-1,-1, 0,-1, 0, 1,-1, 0,-1,-1,-1,-1,-1,
@@ -2326,7 +2322,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.887";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.890";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -7058,7 +7054,7 @@
 						assert((((((CogMethod *) header2))->objectHeader)) == (nullHeaderForMachineCodeMethod())),
 						((((CogMethod *) header2))->methodHeader)));
 				if ((header & (65536 << SmallIntegerShift))
-				 && (localIP == ((GIV(method) + ((LiteralStart + (literalCountOfMethodHeader(header))) * 4)) + (BaseHeaderSize)))) {
+				 && ((((sqInt)localIP)) == ((GIV(method) + ((LiteralStart + (literalCountOfMethodHeader(header))) * 4)) + (BaseHeaderSize)))) {
 					localIP += 3;
 					/* begin fetchNextBytecode */
 					currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
@@ -14848,7 +14844,7 @@
 						assert((((((CogMethod *) header2))->objectHeader)) == (nullHeaderForMachineCodeMethod())),
 						((((CogMethod *) header2))->methodHeader)));
 				if ((header & (65536 << SmallIntegerShift))
-				 && (localIP == ((GIV(method) + ((LiteralStart + (literalCountOfMethodHeader(header))) * 4)) + (BaseHeaderSize)))) {
+				 && ((((sqInt)localIP)) == ((GIV(method) + ((LiteralStart + (literalCountOfMethodHeader(header))) * 4)) + (BaseHeaderSize)))) {
 					localIP += 3;
 					/* begin fetchNextBytecode */
 					currentBytecode = (byteAtPointer(++localIP)) + GIV(bytecodeSetSelector);
@@ -34553,30 +34549,16 @@
 }
 
 
-/*	Pin or unpin the receiver, i.e. make it immobile or mobile. Answer whether
-	the object was
-	already pinned. N.B. pinning does *not* prevent an object from being
-	garbage collected. */
+/*	Pin or unpin the receiver, i.e. make it immobile or mobile, based on the
+	argument. Answer whether the object was already pinned. N.B. pinning does
+	*not* prevent
+	an object from being garbage collected. */
 
 static void
 primitivePin(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     sqInt boolean;
-    sqInt cogMethodOrMethodHeader;
-    sqInt failure;
-    sqInt fmt;
-    sqInt hasYoung;
-    sqInt i;
-    sqInt i1;
-    sqInt newObj;
-    usqInt numSlots;
-    usqInt numSlots1;
     sqInt obj;
-    sqInt oldClone;
-    sqInt oop;
-    sqInt rawHeader;
-    sqInt referent;
-    SpurSegmentInfo *seg;
     char *sp;
     sqInt wasPinned;
 
@@ -34601,145 +34583,15 @@
 		wasPinned = GIV(trueObj);
 		/* begin setIsPinnedOf:to: */
 		flag("endianness");
-		longAtput(obj, (longAt(obj)) & (~(1 << 30)));
+		longAtput(obj, (boolean == GIV(trueObj)
+			? (longAt(obj)) | (1 << 30)
+			: (longAt(obj)) & (~(1 << 30))));
 	}
 	else {
 		wasPinned = GIV(falseObj);
-		/* begin pinObject: */
-		assert(isNonImmediate(obj));
-		flag("policy decision here. if already old, do we clone in a segment containing pinned objects or merely pin?");
-		if (isOldObject(obj)) {
-			/* begin segmentContainingObj: */
-			for (i = (GIV(numSegments) - 1); i >= 0; i += -1) {
-				if (obj >= (((GIV(segments)[i]).segStart))) {
-					seg = (&(GIV(segments)[i]));
-					goto l1;
-				}
-			}
-			seg = null;
-		l1:	/* end segmentContainingObj: */;
-			if ((seg->containsPinned)) {
-				/* begin setIsPinnedOf:to: */
-				flag("endianness");
-				longAtput(obj, (longAt(obj)) | (1 << 30));
-				failure = 0;
-				goto l2;
-			}
-			if (!(someSegmentContainsPinned())) {
-				/* begin setIsPinnedOf:to: */
-				flag("endianness");
-				longAtput(obj, (longAt(obj)) | (1 << 30));
-				(seg->containsPinned = 1);
-				failure = 0;
-				goto l2;
-			}
-		}
-		/* begin cloneInOldSpaceForPinning: */
-		/* begin numSlotsOf: */
-		flag("endianness");
-		assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun()));
-		numSlots1 = byteAt(obj + 7);
-		numSlots = (numSlots1 == 0xFF
-			? longAt(obj - (BaseHeaderSize))
-			: numSlots1);
-		fmt = (((usqInt) (longAt(obj))) >> 24) & 0x1F;
-		newObj = allocateSlotsForPinningInOldSpacebytesformatclassIndex(numSlots, ((numSlots == 0
-	? 8
-	: (numSlots + (numSlots & 1)) << 2)) + ((numSlots >= 0xFF
-	? (BaseHeaderSize) + (BaseHeaderSize)
-	: BaseHeaderSize)), fmt, (longAt(obj)) & 0x3FFFFF);
-		if (fmt <= 5) {
-			hasYoung = 0;
-			for (i1 = 0; i1 < numSlots; i1 += 1) {
-				oop = longAt((obj + (BaseHeaderSize)) + (i1 << 2));
-				if (((oop & 3) == 0)
-				 && (((longAt(oop)) & (0x3FFFFF - 8)) == 0)) {
-					/* begin followForwarded: */
-					assert(isUnambiguouslyForwarder(oop));
-					referent = longAt((oop + (BaseHeaderSize)) + (0 << 2));
-					while (((referent & 3) == 0)
-					 && (((longAt(referent)) & 0x3FFFFF) == 8)) {
-						referent = longAt((referent + (BaseHeaderSize)) + (0 << 2));
-					}
-					oop = referent;
-				}
-				if (((oop & 3) == 0)
-				 && (isYoungObject(oop))) {
-					hasYoung = 1;
-				}
-				/* begin storePointerUnchecked:ofObject:withValue: */
-				assert(!(isForwarded(newObj)));
-				longAtput((newObj + (BaseHeaderSize)) + (i1 << 2), oop);
-			}
-			if (hasYoung
-			 && (!(isYoungObject(newObj)))) {
-				remember(newObj);
-			}
-		}
-		else {
-			for (i1 = 0; i1 < numSlots; i1 += 1) {
-				/* begin storePointerUnchecked:ofObject:withValue: */
-				assert(!(isForwarded(newObj)));
-				longAtput((newObj + (BaseHeaderSize)) + (i1 << 2), longAt((obj + (BaseHeaderSize)) + (i1 << 2)));
-			}
-			if (fmt >= 24) {
-				/* begin maybeFixClonedCompiledMethod: */
-				assert(isOopCompiledMethod(newObj));
-				rawHeader = longAt((newObj + (BaseHeaderSize)) + (HeaderIndex << 2));
-				if (isCogMethodReference(rawHeader)) {
-					/* begin rawHeaderOf:put: */
-					cogMethodOrMethodHeader = ((((CogMethod *) rawHeader))->methodHeader);
-					assert(isCompiledMethodHeader(headerWhileForwardingOf(newObj)));
-					/* begin storePointerUnchecked:ofObject:withValue: */
-					assert(!(isForwarded(newObj)));
-					longAtput((newObj + (BaseHeaderSize)) + (HeaderIndex << 2), cogMethodOrMethodHeader);
-				}
-				if ((isOldObject(newObj))
-				 && ((isYoungObject(obj))
-				 || (((((usqInt) (longAt(obj))) >> 29) & 1) != 0))) {
-					remember(newObj);
-				}
-			}
-		}
-		oldClone = newObj;
-		if (oldClone == 0) {
-			failure = PrimErrNoMemory;
-			goto l2;
-		}
-		/* 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(obj, ((longAt(obj)) & (~((0x1F << 24) + 0x3FFFFF))) + (8 + (7 << 24)));
-		/* begin storePointer:ofForwarder:withValue: */
-		assert(isForwarded(obj));
-		assert(!(isOopForwarded(oldClone)));
-		if (isOldObject(obj)) {
-
-			/* most stores into young objects */
-
-			if (((oldClone & 3) == 0)
-			 && ((((usqInt) oldClone)) < (((usqInt) GIV(newSpaceLimit))))) {
-				/* begin possibleRootStoreInto: */
-				if (!(((((usqInt) (longAt(obj))) >> 29) & 1) != 0)) {
-					remember(obj);
-				}
-			}
-		}
-		longAtput((obj + (BaseHeaderSize)) + (0 << 2), oldClone);
-		if ((byteAt(obj + 7)) == 0) {
-			/* begin setRawNumSlotsOf:to: */
-			flag("endian");
-			byteAtput(obj + 7, 1);
-		}
-		failure = 0;
-	l2:	/* end pinObject: */;
-		if (failure != 0) {
-			(GIV(primFailCode) = failure);
+		if (((boolean == GIV(trueObj))
+ && (pinObject(obj))) == 0) {
+			(GIV(primFailCode) = PrimErrNoMemory);
 			return;
 		}
 	}
@@ -38618,9 +38470,9 @@
 	if ((((usqInt) (limitSeg + bodySize))) >= (((usqInt) stopAddr))) {
 		return 0;
 	}
-	memcpy(limitSeg, ((byteAt(objOop + 7)) == 0xFF
-		? objOop - (BaseHeaderSize)
-		: objOop), bodySize);
+	memcpy(((void *)limitSeg), ((void *)(((byteAt(objOop + 7)) == 0xFF
+	? objOop - (BaseHeaderSize)
+	: objOop))), bodySize);
 	/* begin objectStartingAt: */
 	numSlots = byteAt(limitSeg + 7);
 	copy = (numSlots == 0xFF
@@ -39173,7 +39025,8 @@
 
 
 /*	Answer the oop of a chunk of space in oldSpace with numSlots slots. The
-	header will have been filled-in but not the contents. */
+	header will have been filled-in but not the contents. If no memory is
+	available answer nil. */
 
 static sqInt
 allocateSlotsInOldSpacebytesformatclassIndex(sqInt numSlots, usqInt totalBytes, sqInt formatField, sqInt classIndex)
@@ -41194,41 +41047,66 @@
 static sqInt
 allInstancesOf(sqInt aClass)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt actualIndex;
     sqInt address;
     sqInt address1;
+    sqInt address11;
+    sqInt address2;
     usqInt bytes;
     usqInt bytes1;
+    sqInt c;
     sqInt classIndex;
+    sqInt classOrNil;
     sqInt count;
+    sqInt count1;
+    sqInt count2;
+    sqInt entry;
+    sqInt expectedIndex;
+    sqInt expectedIndex1;
     sqInt freeChunk;
-    sqInt freeChunk1;
     sqInt i;
+    sqInt i1;
+    sqInt index;
+    sqInt j;
+    sqInt jLimiT;
     sqInt limit;
     sqInt limit1;
+    sqInt limit11;
     sqInt newObj;
     sqInt newObj1;
-    sqInt next;
     usqInt numBytes;
     usqInt numBytes1;
     usqInt numSlots;
     usqInt numSlots1;
+    usqInt numSlots11;
+    usqInt numSlots12;
     usqInt numSlots2;
     usqInt numSlots3;
     sqInt obj;
+    sqInt obj1;
     sqInt objOop;
     sqInt objOop1;
+    sqInt objOop11;
+    sqInt objOop2;
+    sqInt p;
+    sqInt page;
     sqInt prevObj;
     sqInt prevObj1;
+    sqInt prevObj11;
+    sqInt prevObj2;
     sqInt prevPrevObj;
     sqInt prevPrevObj1;
+    sqInt prevPrevObj11;
+    sqInt prevPrevObj2;
     sqInt ptr;
+    sqInt ptr1;
+    sqInt ptr2;
     sqInt slotBytes;
     sqInt smallObj;
     sqInt start;
 
 	classIndex = (longAt(aClass + 4)) & 0x3FFFFF;
-	if ((classIndex == 0)
-	 || (aClass != (classOrNilAtIndex(classIndex)))) {
+	if (classIndex == 0) {
 		/* begin allocateSlots:format:classIndex: */
 		newObj = GIV(freeStart);
 		numBytes = (BaseHeaderSize) + (8);
@@ -41252,26 +41130,8 @@
 		return freeChunk;
 	}
 	
-	/* begin allocateLargestFreeChunk */
-	freeChunk1 = findLargestFreeChunk();
-	if (!(freeChunk1)) {
-		freeChunk = null;
-		goto l3;
-	}
-	next = longAt((freeChunk1 + (BaseHeaderSize)) + (0 << 2));
-	if (next != 0) {
-		/* begin storePointer:ofFreeChunk:withValue: */
-		assert(isFreeObject(freeChunk1));
-		assert(((longAt((next + (BaseHeaderSize)) + (0 << 2))) == 0)
-		 || (isFreeObject(longAt((next + (BaseHeaderSize)) + (0 << 2)))));
-		longAtput((freeChunk1 + (BaseHeaderSize)) + (0 << 2), longAt((next + (BaseHeaderSize)) + (0 << 2)));
-		freeChunk = next;
-		goto l3;
-	}
-	unlinkSolitaryFreeTreeNode(freeChunk1);
-	freeChunk = freeChunk1;
-l3:	/* end allocateLargestFreeChunk */;
-	ptr = (start = freeChunk + (BaseHeaderSize));
+	freeChunk = allocateLargestFreeChunk();
+	start = freeChunk + (BaseHeaderSize);
 	/* begin addressAfter: */
 	/* begin numSlotsOfAny: */
 	numSlots1 = byteAt(freeChunk + 7);
@@ -41282,112 +41142,274 @@
 		? 8
 		: (numSlots + (numSlots & 1)) << 2);
 	limit = (freeChunk + (BaseHeaderSize)) + slotBytes;
-	count = 0;
-	/* begin allHeapEntitiesDo: */
-	/* begin allOldSpaceEntitiesDo: */
-	/* begin allOldSpaceEntitiesFrom:do: */
-	assert(isOldObject(GIV(nilObj)));
-	prevPrevObj1 = (prevObj1 = null);
-	objOop1 = GIV(nilObj);
-	while (1) {
-		assert((objOop1 % (allocationUnit())) == 0);
-		if (!((((usqInt) objOop1)) < (((usqInt) GIV(endOfMemory))))) break;
-		assert((long64At(objOop1)) != 0);
+	if (isClassAtUniqueIndex(aClass)) {
+		/* begin uniqueIndex:allInstancesInto:limit:resultsInto: */
+		count1 = 0;
+		ptr1 = start;
+		/* begin allHeapEntitiesDo: */
+		/* begin allOldSpaceEntitiesDo: */
+		/* begin allOldSpaceEntitiesFrom:do: */
+		assert(isOldObject(GIV(nilObj)));
+		prevPrevObj = (prevObj = null);
+		objOop = GIV(nilObj);
+		while (1) {
+			assert((objOop % (allocationUnit())) == 0);
+			if (!((((usqInt) objOop)) < (((usqInt) GIV(endOfMemory))))) break;
+			assert((long64At(objOop)) != 0);
+			
+			/* continue enumerating even if no room so as to unmark all objects. */
+
+			if (1) {
+				if (((longAt(objOop)) & 0x3FFFFF) > 0x1F) {
+					;
+					if (((longAt(objOop)) & 0x3FFFFF) == classIndex) {
+						count1 += 1;
+						if (ptr1 < limit) {
+							longAtput(ptr1, objOop);
+							ptr1 += 4;
+						}
+					}
+				}
+				else {
+					;
+				}
+			}
+
+			prevPrevObj = prevObj;
+			prevObj = objOop;
+			objOop = objectAfterlimit(objOop, GIV(endOfMemory));
+		}
 		
-		/* continue enumerating even if no room so as to unmark all objects. */
+		
+		/* begin allNewSpaceEntitiesDo: */
 
-		if (1) {
-			if (((longAt(objOop1)) & 0x3FFFFF) > 0x1F) {
-				;
-				if (((longAt(objOop1)) & 0x3FFFFF) == classIndex) {
-					count += 1;
-					if (ptr < limit) {
-						longAtput(ptr, objOop1);
-						ptr += 4;
+		/* After a scavenge eden is empty, futureSpace is empty, and all newSpace objects are
+		   in pastSpace.  Objects are allocated in eden.  So enumerate only pastSpace and eden. */
+
+		prevPrevObj1 = (prevObj1 = null);
+		assert((((pastSpace()).start)) < (((eden()).start)));
+		/* begin objectStartingAt: */
+		address = ((pastSpace()).start);
+		numSlots2 = byteAt(address + 7);
+		objOop1 = (numSlots2 == 0xFF
+			? address + (BaseHeaderSize)
+			: address);
+		limit1 = GIV(pastSpaceStart);
+		while ((((usqInt) objOop1)) < (((usqInt) limit1))) {
+			
+			/* continue enumerating even if no room so as to unmark all objects. */
+
+			if (1) {
+				if (((longAt(objOop1)) & 0x3FFFFF) > 0x1F) {
+					;
+					if (((longAt(objOop1)) & 0x3FFFFF) == classIndex) {
+						count1 += 1;
+						if (ptr1 < limit) {
+							longAtput(ptr1, objOop1);
+							ptr1 += 4;
+						}
 					}
 				}
+				else {
+					;
+				}
 			}
-			else {
-				;
+
+			prevPrevObj1 = prevObj1;
+			prevObj1 = objOop1;
+			objOop1 = objectAfterlimit(objOop1, limit1);
+		}
+		/* begin objectStartingAt: */
+		address1 = ((eden()).start);
+		numSlots11 = byteAt(address1 + 7);
+		objOop1 = (numSlots11 == 0xFF
+			? address1 + (BaseHeaderSize)
+			: address1);
+		while ((((usqInt) objOop1)) < (((usqInt) GIV(freeStart)))) {
+			
+			/* continue enumerating even if no room so as to unmark all objects. */
+
+			if (1) {
+				if (((longAt(objOop1)) & 0x3FFFFF) > 0x1F) {
+					;
+					if (((longAt(objOop1)) & 0x3FFFFF) == classIndex) {
+						count1 += 1;
+						if (ptr1 < limit) {
+							longAtput(ptr1, objOop1);
+							ptr1 += 4;
+						}
+					}
+				}
+				else {
+					;
+				}
 			}
+
+			prevPrevObj1 = prevObj1;
+			prevObj1 = objOop1;
+			objOop1 = objectAfterlimit(objOop1, GIV(freeStart));
 		}
+		
+		
+		count = count1;
+		ptr = ptr1;
 
-		prevPrevObj1 = prevObj1;
-		prevObj1 = objOop1;
-		objOop1 = objectAfterlimit(objOop1, GIV(endOfMemory));
 	}
-	
-	
-	/* begin allNewSpaceEntitiesDo: */
+	else {
+		/* begin ambiguousClass:allInstancesInto:limit:resultsInto: */
+		count2 = 0;
+		ptr2 = start;
+		expectedIndex = (longAt(aClass + 4)) & 0x3FFFFF;
+		/* begin allHeapEntitiesDo: */
+		/* begin allOldSpaceEntitiesDo: */
+		/* begin allOldSpaceEntitiesFrom:do: */
+		assert(isOldObject(GIV(nilObj)));
+		prevPrevObj11 = (prevObj11 = null);
+		objOop11 = GIV(nilObj);
+		while (1) {
+			assert((objOop11 % (allocationUnit())) == 0);
+			if (!((((usqInt) objOop11)) < (((usqInt) GIV(endOfMemory))))) break;
+			assert((long64At(objOop11)) != 0);
+			
+			/* continue enumerating even if no room so as to unmark all objects and/or normalize class indices. */
 
-	/* After a scavenge eden is empty, futureSpace is empty, and all newSpace objects are
-	   in pastSpace.  Objects are allocated in eden.  So enumerate only pastSpace and eden. */
+			if (1) {
+				if (((longAt(objOop11)) & 0x3FFFFF) > 0x1F) {
+					;
+					actualIndex = (longAt(objOop11)) & 0x3FFFFF;
+					if ((classOrNilAtIndex(actualIndex)) == aClass) {
+						if (actualIndex != expectedIndex) {
+							/* begin setClassIndexOf:to: */
+							assert(((expectedIndex >= 0) && (expectedIndex <= (classIndexMask()))));
+							flag("endianness");
+							longAtput(objOop11, ((longAt(objOop11)) & (~0x3FFFFF)) + expectedIndex);
+						}
+						count2 += 1;
+						if (ptr2 < limit) {
+							longAtput(ptr2, objOop11);
+							ptr2 += 4;
+						}
+					}
+				}
+				else {
+					;
+				}
+			}
 
-	prevPrevObj = (prevObj = null);
-	assert((((pastSpace()).start)) < (((eden()).start)));
-	/* begin objectStartingAt: */
-	address = ((pastSpace()).start);
-	numSlots2 = byteAt(address + 7);
-	objOop = (numSlots2 == 0xFF
-		? address + (BaseHeaderSize)
-		: address);
-	limit1 = GIV(pastSpaceStart);
-	while ((((usqInt) objOop)) < (((usqInt) limit1))) {
+			prevPrevObj11 = prevObj11;
+			prevObj11 = objOop11;
+			objOop11 = objectAfterlimit(objOop11, GIV(endOfMemory));
+		}
 		
-		/* continue enumerating even if no room so as to unmark all objects. */
+		
+		/* begin allNewSpaceEntitiesDo: */
 
-		if (1) {
-			if (((longAt(objOop)) & 0x3FFFFF) > 0x1F) {
-				;
-				if (((longAt(objOop)) & 0x3FFFFF) == classIndex) {
-					count += 1;
-					if (ptr < limit) {
-						longAtput(ptr, objOop);
-						ptr += 4;
+		/* After a scavenge eden is empty, futureSpace is empty, and all newSpace objects are
+		   in pastSpace.  Objects are allocated in eden.  So enumerate only pastSpace and eden. */
+
+		prevPrevObj2 = (prevObj2 = null);
+		assert((((pastSpace()).start)) < (((eden()).start)));
+		/* begin objectStartingAt: */
+		address2 = ((pastSpace()).start);
+		numSlots3 = byteAt(address2 + 7);
+		objOop2 = (numSlots3 == 0xFF
+			? address2 + (BaseHeaderSize)
+			: address2);
+		limit11 = GIV(pastSpaceStart);
+		while ((((usqInt) objOop2)) < (((usqInt) limit11))) {
+			
+			/* continue enumerating even if no room so as to unmark all objects and/or normalize class indices. */
+
+			if (1) {
+				if (((longAt(objOop2)) & 0x3FFFFF) > 0x1F) {
+					;
+					actualIndex = (longAt(objOop2)) & 0x3FFFFF;
+					if ((classOrNilAtIndex(actualIndex)) == aClass) {
+						if (actualIndex != expectedIndex) {
+							/* begin setClassIndexOf:to: */
+							assert(((expectedIndex >= 0) && (expectedIndex <= (classIndexMask()))));
+							flag("endianness");
+							longAtput(objOop2, ((longAt(objOop2)) & (~0x3FFFFF)) + expectedIndex);
+						}
+						count2 += 1;
+						if (ptr2 < limit) {
+							longAtput(ptr2, objOop2);
+							ptr2 += 4;
+						}
 					}
 				}
+				else {
+					;
+				}
 			}
-			else {
-				;
-			}
+
+			prevPrevObj2 = prevObj2;
+			prevObj2 = objOop2;
+			objOop2 = objectAfterlimit(objOop2, limit11);
 		}
+		/* begin objectStartingAt: */
+		address11 = ((eden()).start);
+		numSlots12 = byteAt(address11 + 7);
+		objOop2 = (numSlots12 == 0xFF
+			? address11 + (BaseHeaderSize)
+			: address11);
+		while ((((usqInt) objOop2)) < (((usqInt) GIV(freeStart)))) {
+			
+			/* continue enumerating even if no room so as to unmark all objects and/or normalize class indices. */
 
-		prevPrevObj = prevObj;
-		prevObj = objOop;
-		objOop = objectAfterlimit(objOop, limit1);
-	}
-	/* begin objectStartingAt: */
-	address1 = ((eden()).start);
-	numSlots3 = byteAt(address1 + 7);
-	objOop = (numSlots3 == 0xFF
-		? address1 + (BaseHeaderSize)
-		: address1);
-	while ((((usqInt) objOop)) < (((usqInt) GIV(freeStart)))) {
-		
-		/* continue enumerating even if no room so as to unmark all objects. */
+			if (1) {
+				if (((longAt(objOop2)) & 0x3FFFFF) > 0x1F) {
+					;
+					actualIndex = (longAt(objOop2)) & 0x3FFFFF;
+					if ((classOrNilAtIndex(actualIndex)) == aClass) {
+						if (actualIndex != expectedIndex) {
+							/* begin setClassIndexOf:to: */
+							assert(((expectedIndex >= 0) && (expectedIndex <= (classIndexMask()))));
+							flag("endianness");
+							longAtput(objOop2, ((longAt(objOop2)) & (~0x3FFFFF)) + expectedIndex);
+						}
+						count2 += 1;
+						if (ptr2 < limit) {
+							longAtput(ptr2, objOop2);
+							ptr2 += 4;
+						}
+					}
+				}
+				else {
+					;
+				}
+			}
 
-		if (1) {
-			if (((longAt(objOop)) & 0x3FFFFF) > 0x1F) {
-				;
-				if (((longAt(objOop)) & 0x3FFFFF) == classIndex) {
-					count += 1;
-					if (ptr < limit) {
-						longAtput(ptr, objOop);
-						ptr += 4;
+			prevPrevObj2 = prevObj2;
+			prevObj2 = objOop2;
+			objOop2 = objectAfterlimit(objOop2, GIV(freeStart));
+		}
+		
+		
+		/* begin purgeDuplicateClassTableEntriesFor: */
+		expectedIndex1 = (longAt(aClass + 4)) & 0x3FFFFF;
+		/* begin classTableEntriesDo: */
+		for (i1 = 0; i1 < GIV(numClassTablePages); i1 += 1) {
+			page = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i1 << 2));
+			for (j = 0, jLimiT = ((1 << 10) - 1); j <= jLimiT; j += 1) {
+				classOrNil = longAt((page + (BaseHeaderSize)) + (j << 2));
+				if (classOrNil != GIV(nilObj)) {
+					index = (i1 << 10) + j;
+					if ((classOrNil == aClass)
+					 && (index != expectedIndex1)) {
+						classAtIndexput(index, GIV(nilObj));
+						if (index < GIV(classTableIndex)) {
+							GIV(classTableIndex) = index;
+						}
 					}
+
 				}
 			}
-			else {
-				;
-			}
 		}
+		count = count2;
+		ptr = ptr2;
 
-		prevPrevObj = prevObj;
-		prevObj = objOop;
-		objOop = objectAfterlimit(objOop, GIV(freeStart));
 	}
-	
-	
 	assert(isEmptyObjStack(GIV(markStack)));
 	assert(isEmptyObjStack(GIV(weaklingStack)));
 
@@ -41500,10 +41522,8 @@
     usqInt bytes;
     sqInt count;
     sqInt freeChunk;
-    sqInt freeChunk1;
     sqInt limit;
     sqInt limit1;
-    sqInt next;
     usqInt numSlots;
     usqInt numSlots1;
     usqInt numSlots2;
@@ -41520,25 +41540,7 @@
     sqInt start;
 
 	
-	/* begin allocateLargestFreeChunk */
-	freeChunk1 = findLargestFreeChunk();
-	if (!(freeChunk1)) {
-		freeChunk = null;
-		goto l1;
-	}
-	next = longAt((freeChunk1 + (BaseHeaderSize)) + (0 << 2));
-	if (next != 0) {
-		/* begin storePointer:ofFreeChunk:withValue: */
-		assert(isFreeObject(freeChunk1));
-		assert(((longAt((next + (BaseHeaderSize)) + (0 << 2))) == 0)
-		 || (isFreeObject(longAt((next + (BaseHeaderSize)) + (0 << 2)))));
-		longAtput((freeChunk1 + (BaseHeaderSize)) + (0 << 2), longAt((next + (BaseHeaderSize)) + (0 << 2)));
-		freeChunk = next;
-		goto l1;
-	}
-	unlinkSolitaryFreeTreeNode(freeChunk1);
-	freeChunk = freeChunk1;
-l1:	/* end allocateLargestFreeChunk */;
+	freeChunk = allocateLargestFreeChunk();
 	ptr = (start = freeChunk + (BaseHeaderSize));
 	/* begin addressAfter: */
 	/* begin numSlotsOfAny: */
@@ -41819,6 +41821,35 @@
 }
 
 
+/*	Answer the largest free chunk in the free lists. */
+/*	would like to use ifNotNil: but the ^next inside the ^blah ifNotNil:
+	confused Slang
+ */
+
+static sqInt
+allocateLargestFreeChunk(void)
+{
+    sqInt freeChunk;
+    sqInt next;
+
+	freeChunk = findLargestFreeChunk();
+	if (!(freeChunk)) {
+		return null;
+	}
+	next = longAt((freeChunk + (BaseHeaderSize)) + (0 << 2));
+	if (next != 0) {
+		/* begin storePointer:ofFreeChunk:withValue: */
+		assert(isFreeObject(freeChunk));
+		assert(((longAt((next + (BaseHeaderSize)) + (0 << 2))) == 0)
+		 || (isFreeObject(longAt((next + (BaseHeaderSize)) + (0 << 2)))));
+		longAtput((freeChunk + (BaseHeaderSize)) + (0 << 2), longAt((next + (BaseHeaderSize)) + (0 << 2)));
+		return next;
+	}
+	unlinkSolitaryFreeTreeNode(freeChunk);
+	return freeChunk;
+}
+
+
 /*	Allocate an object with numSlots in newSpace. This is for the `ee'
 	execution engine allocations,
 	and must be satisfied. If no memory is available, abort. If the allocation
@@ -42230,10 +42261,8 @@
     sqInt newObj2;
     sqInt next;
     sqInt o1ClassIndex;
-    sqInt o1HashBits;
     sqInt o1HasYoung;
     sqInt o2ClassIndex;
-    sqInt o2HashBits;
     sqInt o2HasYoung;
     sqInt obj;
     sqInt obj1;
@@ -42782,8 +42811,6 @@
 			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()))));
@@ -42811,36 +42838,17 @@
 					flag("endian");
 					byteAtput(obj11 + 7, 1);
 				}
-				if ((isOldObject(obj11))
-				 && (isYoungObject(obj21))) {
-					GIV(becomeEffectsFlags) = GIV(becomeEffectsFlags) | OldBecameNewFlag;
-				}
 				if (copyHashFlag) {
 					/* begin setHashBitsOf:to: */
 					flag("endianness");
-					assert(((o1HashBits >= 0) && (o1HashBits <= (identityHashHalfWordMask()))));
-					longAtput(obj21 + 4, ((((longAt(obj21 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + o1HashBits);
+					assert(((((longAt(obj11 + 4)) & 0x3FFFFF) >= 0) && (((longAt(obj11 + 4)) & 0x3FFFFF) <= (identityHashHalfWordMask()))));
+					longAtput(obj21 + 4, ((((longAt(obj21 + 4)) | 0x3FFFFF) - 0x3FFFFF)) + ((longAt(obj11 + 4)) & 0x3FFFFF));
 				}
-				if ((o1HashBits != 0)
-				 && ((classAtIndex(o1HashBits)) == obj11)) {
-					expungeFromClassTable(obj11);
+				if ((isOldObject(obj11))
+				 && (isYoungObject(obj21))) {
+					GIV(becomeEffectsFlags) = GIV(becomeEffectsFlags) | OldBecameNewFlag;
 				}
-				else {
-					o1HashBits = 0;
-				}
 				assert(!((isForwarded(obj21))));
-				if (o1HashBits != 0) {
-					if (o2HashBits == 0) {
-
-						/* obj2 has no hash; we're free to assign one */
-
-						/* begin setHashBitsOf:to: */
-						flag("endianness");
-						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));
 				if (((objOop4 & 3) == 0)
@@ -45231,29 +45239,6 @@
 	assert(isValidObjStack(objStack));
 }
 
-
-/*	The classTableBitmap is used to reclaim unused and/or duplicate entries
-	in the classTable. As such it is notionally 2^(22 - 3) bytes big, or 512k,
-	a little too large to be comfortable allocating statically (especially on
-	small machines). So make it big enough for the max classTableIndex's base
-	2 ceiling. */
-
-static void
-ensureAdequateClassTableBitmap(void)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt requiredSize;
-
-	requiredSize = (1 << (highBit(GIV(numClassTablePages)))) * ((1 << 10) / BitsPerByte);
-	if (!(GIV(classTableBitmap) == null)) {
-		free(GIV(classTableBitmap));
-	}
-	GIV(classTableBitmap) = malloc(requiredSize);
-	if (!(GIV(classTableBitmap))) {
-		error("could not allocate classTableBitmap");
-	}
-	memset(GIV(classTableBitmap), 0, requiredSize);
-}
-
 static sqInt
 ensureBehaviorHash(sqInt aBehavior)
 {
@@ -45464,7 +45449,6 @@
 				assert(((GIV(classTableIndex) >= 0) && (GIV(classTableIndex) <= (identityHashHalfWordMask()))));
 				longAtput(aBehavior + 4, ((((longAt(aBehavior + 4)) | 0x3FFFFF) - 0x3FFFFF)) + GIV(classTableIndex));
 				assert((classAtIndex(rawHashBitsOf(aBehavior))) == aBehavior);
-				ensureAdequateClassTableBitmap();
 				return 0;
 			}
 		}
@@ -45548,108 +45532,6 @@
 	return 0;
 }
 
-
-/*	Bits have been set in the classTableBitmap corresponding to
-	used classes. Any class in the class table that does not have a
-	bit set has no instances with that class index. However, becomeForward:
-	can create duplicate entries, and these duplicate entries
-	a) won't have a bit set on load (because there are no forwarders on load),
-	b) wont match their identityHash.
-	So expunge duplicates by eliminating unmarked entries that don't occur at
-	their identityHash.
-	Further, any class in the table that is unmarked will also not have a bit
-	set so
-	eliminate unmarked classes using the bitmap too. */
-
-static void
-expungeDuplicateAndUnmarkedClasses(sqInt expungeUnmarked)
-{   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt byte;
-    sqInt byteIndex;
-    sqInt classIndex;
-    sqInt classOrNil;
-    sqInt classTablePage;
-    sqInt i;
-    sqInt majorBitIndex;
-    sqInt majorBitIndexLimiT;
-    sqInt minorBitIndex;
-
-	for (i = 1; i < GIV(numClassTablePages); i += 1) {
-
-		/* Avoid expunging the puns by not scanning the 0th page. */
-		/* optimize scan by only scanning bitmap in regions that have pages. */
-
-		classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i << 2));
-		if (classTablePage != GIV(nilObj)) {
-			for (majorBitIndex = (i << 10), majorBitIndexLimiT = ((i << 10) + ((1 << 10) - 1)); majorBitIndex <= majorBitIndexLimiT; majorBitIndex += 8) {
-
-				/* optimize scan by scanning a byte of indices (8 indices) at a time */
-
-				byteIndex = majorBitIndex / BitsPerByte;
-				byte = GIV(classTableBitmap)[byteIndex];
-				if (byte != 0xFF) {
-					for (minorBitIndex = 0; minorBitIndex <= 7; minorBitIndex += 1) {
-						if ((byte & (1 << minorBitIndex)) == 0) {
-							classIndex = majorBitIndex + minorBitIndex;
-							classOrNil = longAt((classTablePage + (BaseHeaderSize)) + ((classIndex & ((1 << 10) - 1)) << 2));
-							assert((classAtIndex(classIndex)) == classOrNil);
-							assert((classOrNil == GIV(nilObj))
-							 || (addressCouldBeClassObj(classOrNil)));
-							if (classOrNil == GIV(nilObj)) {
-								if (classIndex < GIV(classTableIndex)) {
-									GIV(classTableIndex) = classIndex;
-								}
-							}
-							else {
-								if ((expungeUnmarked
-								 && (!(((((usqInt) (longAt(classOrNil + 4))) >> 23) & 1) != 0)))
-								 || (((longAt(classOrNil + 4)) & 0x3FFFFF) != classIndex)) {
-									/* begin storePointerUnchecked:ofObject:withValue: */
-									assert(!(isForwarded(classTablePage)));
-									longAtput((classTablePage + (BaseHeaderSize)) + ((classIndex & ((1 << 10) - 1)) << 2), GIV(nilObj));
-									assert((expungeUnmarked
-									 && (!(isMarked(classOrNil))))
-									 || ((classAtIndex(rawHashBitsOf(classOrNil))) == classOrNil));
-									if (classIndex < GIV(classTableIndex)) {
-										GIV(classTableIndex) = classIndex;
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-
-/*	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
@@ -46042,19 +45924,6 @@
 	return 16;
 }
 
-
-/*	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
-firstClassIndexPun(void)
-{
-	return 16;
-}
-
 sqInt
 firstCompiledMethodFormat(void)
 {
@@ -46849,17 +46718,55 @@
 usqLong
 fullGC(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classIndex;
+    sqInt classOrNil;
+    sqInt classTablePage;
+    sqInt i;
+    sqInt j;
+    sqInt jLimiT;
+
 	GIV(needGCFlag) = 0;
 	GIV(gcStartUsecs) = ioUTCMicrosecondsNow();
 	GIV(statMarkCount) = 0;
 	preGCAction(GCModeFull);
 	/* begin globalGarbageCollect */
-	null;
 	assert(validObjStacks());
 	assert(isEmptyObjStack(GIV(markStack)));
 	assert(isEmptyObjStack(GIV(weaklingStack)));
 	markObjects();
-	expungeDuplicateAndUnmarkedClasses(1);
+	/* begin expungeDuplicateAndUnmarkedClasses: */
+	for (i = 1; i < GIV(numClassTablePages); i += 1) {
+
+		/* Avoid expunging the puns by not scanning the 0th page. */
+
+		classTablePage = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (i << 2));
+		for (j = 0, jLimiT = ((1 << 10) - 1); j <= jLimiT; j += 1) {
+			classOrNil = longAt((classTablePage + (BaseHeaderSize)) + (j << 2));
+			classIndex = (i << 10) + j;
+			assert((classOrNil == GIV(nilObj))
+			 || (addressCouldBeClassObj(classOrNil)));
+			if (classOrNil == GIV(nilObj)) {
+				if (classIndex < GIV(classTableIndex)) {
+					GIV(classTableIndex) = classIndex;
+				}
+			}
+			else {
+				if ((1
+				 && (!(((((usqInt) (longAt(classOrNil + 4))) >> 23) & 1) != 0)))
+				 || (((longAt(classOrNil + 4)) & 0x3FFFFF) != classIndex)) {
+					/* begin storePointerUnchecked:ofObject:withValue: */
+					assert(!(isForwarded(classTablePage)));
+					longAtput((classTablePage + (BaseHeaderSize)) + (j << 2), GIV(nilObj));
+					assert((1
+					 && (!(isMarked(classOrNil))))
+					 || ((classAtIndex(rawHashBitsOf(classOrNil))) == classOrNil));
+					if (classIndex < GIV(classTableIndex)) {
+						GIV(classTableIndex) = classIndex;
+					}
+				}
+			}
+		}
+	}
 	nilUnmarkedWeaklingSlots();
 	freeUnmarkedObjectsAndSortAndCoalesceFreeSpaceForPigCompact();
 	runLeakCheckerForFullGCexcludeUnmarkedNewSpaceObjsclassIndicesShouldBeValid(1, 1, 1);
@@ -47216,8 +47123,7 @@
 initializeObjectMemory(sqInt bytesToShift)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
     SpurNewSpaceSpace *aNewSpace;
-    sqInt bit;
-    sqInt bit1;
+    sqInt anOop;
     sqInt classIndex;
     sqInt classTableRoot;
     sqInt field;
@@ -47227,7 +47133,6 @@
     sqInt freeChunk;
     sqInt freeListObj;
     usqLong freeOldStart;
-    sqInt hiddenRoots;
     sqInt i;
     sqInt i1;
     sqInt i2;
@@ -47235,12 +47140,9 @@
     sqInt index;
     sqInt indexLimiT;
     usqLong limit;
-    sqInt majorIndex;
-    sqInt majorIndex1;
     sqInt nilObjPreSwizzle;
     usqInt numSlots;
     usqInt numSlots1;
-    usqInt numSlots11;
     usqInt numSlots2;
     usqInt numSlots3;
     sqInt obj;
@@ -47257,6 +47159,7 @@
 
 	adjustSegmentSwizzlesBy(bytesToShift);
 	/* begin adjustAllOopsBy: */
+	assert(newSpaceIsEmpty());
 	/* begin countNumClassPagesPreSwizzle: */
 	/* begin objectStartingAt: */
 	numSlots2 = byteAt(GIV(oldSpaceStart) + 7);
@@ -47268,10 +47171,10 @@
 	/* begin numSlotsOf: */
 	flag("endianness");
 	assert((classIndexOf(classTableRoot)) > (isForwardedObjectClassIndexPun()));
-	numSlots11 = byteAt(classTableRoot + 7);
-	GIV(numClassTablePages) = ((usqInt) ((numSlots11 == 0xFF
+	numSlots1 = byteAt(classTableRoot + 7);
+	GIV(numClassTablePages) = ((usqInt) ((numSlots1 == 0xFF
 	? longAt(classTableRoot - (BaseHeaderSize))
-	: numSlots11)));
+	: numSlots1)));
 	assert(GIV(numClassTablePages) == ((classTableRootSlots()) + (hiddenRootSlots())));
 	for (i2 = 2; i2 < GIV(numClassTablePages); i2 += 1) {
 		if ((longAt((classTableRoot + (BaseHeaderSize)) + (i2 << 2))) == nilObjPreSwizzle) {
@@ -47280,10 +47183,8 @@
 		}
 	}
 l2:	/* end countNumClassPagesPreSwizzle: */;
-	ensureAdequateClassTableBitmap();
 	if ((bytesToShift != 0)
 	 || ((numSegments()) > 1)) {
-		assert(newSpaceIsEmpty());
 		/* begin objectStartingAt: */
 		numSlots = byteAt(GIV(oldSpaceStart) + 7);
 		obj = (numSlots == 0xFF
@@ -47292,14 +47193,6 @@
 		while ((((usqInt) obj)) < (((usqInt) GIV(freeOldSpaceStart)))) {
 			classIndex = (longAt(obj)) & 0x3FFFFF;
 			if (classIndex >= 8) {
-				if (classIndex > 0x1F) {
-					/* begin inClassTableBitmapSet: */
-					assert((classIndex >= (firstClassIndexPun()))
-					 && (classIndex <= (classIndexMask())));
-					majorIndex = classIndex / BitsPerByte;
-					bit = 1 << (classIndex & (BitsPerByte - 1));
-					GIV(classTableBitmap)[majorIndex] = ((GIV(classTableBitmap)[majorIndex]) | bit);
-				}
 				/* begin swizzleFieldsOfObject: */
 				fieldAddr = obj + (lastPointerOfWhileSwizzling(obj));
 				while ((((usqInt) fieldAddr)) >= (((usqInt) (obj + (BaseHeaderSize))))) {
@@ -47334,26 +47227,6 @@
 			obj = objectAfter(obj);
 		}
 	}
-	else {
-		assert(newSpaceIsEmpty());
-		/* begin objectStartingAt: */
-		numSlots1 = byteAt(GIV(oldSpaceStart) + 7);
-		obj = (numSlots1 == 0xFF
-			? GIV(oldSpaceStart) + (BaseHeaderSize)
-			: GIV(oldSpaceStart));
-		while ((((usqInt) obj)) < (((usqInt) GIV(endOfMemory)))) {
-			classIndex = (longAt(obj)) & 0x3FFFFF;
-			if (classIndex > 0x1F) {
-				/* begin inClassTableBitmapSet: */
-				assert((classIndex >= (firstClassIndexPun()))
-				 && (classIndex <= (classIndexMask())));
-				majorIndex1 = classIndex / BitsPerByte;
-				bit1 = 1 << (classIndex & (BitsPerByte - 1));
-				GIV(classTableBitmap)[majorIndex1] = ((GIV(classTableBitmap)[majorIndex1]) | bit1);
-			}
-			obj = objectAfter(obj);
-		}
-	}
 
 	/* heavily used special objects */
 
@@ -47370,10 +47243,9 @@
 	assert(GIV(falseObj) == (objectAfter(GIV(nilObj))));
 	assert(GIV(trueObj) == (objectAfter(GIV(falseObj))));
 	freeListObj = objectAfter(GIV(trueObj));
-	/* begin reInitializeClassTablePostLoad: */
-	hiddenRoots = objectAfter(freeListObj);
 	/* begin hiddenRootsObj: */
-	GIV(hiddenRootsObj) = hiddenRoots;
+	anOop = objectAfter(freeListObj);
+	GIV(hiddenRootsObj) = anOop;
 	assert(validClassTableRootPages());
 	GIV(classTableFirstPage) = longAt((GIV(hiddenRootsObj) + (BaseHeaderSize)) + (0 << 2));
 	assert(((numSlotsOf(GIV(classTableFirstPage))) - 1) == (classTableMinorIndexMask()));
@@ -47387,7 +47259,6 @@
 	}
 	GIV(classTableIndex) = 1 << 10;
 l1:	/* end hiddenRootsObj: */;
-	expungeDuplicateAndUnmarkedClasses(0);
 	GIV(markStack) = swizzleObjStackAt(MarkStackRootIndex);
 	GIV(weaklingStack) = swizzleObjStackAt(WeaklingStackRootIndex);
 	GIV(ephemeronQueue) = swizzleObjStackAt(EphemeronQueueRootIndex);
@@ -47588,6 +47459,40 @@
 }
 
 
+/*	Answer if aClass exists at only one index in the class table. */
+
+static sqInt
+isClassAtUniqueIndex(sqInt aClass)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt classOrNil;
+    sqInt entry;
+    sqInt expectedIndex;
+    sqInt i;
+    sqInt index;
+    sqInt j;
+    sqInt jLimiT;
+    sqInt page;
+
+	expectedIndex = (longAt(aClass + 4)) & 0x3FFFFF;
+	/* begin classTableEntriesDo: */
+	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)) {
+				index = (i << 10) + j;
+				if ((classOrNil == aClass)
+				 && (index != expectedIndex)) {
+					return 0;
+				}
+
+			}
+		}
+	}
+	return 1;
+}
+
+
 /*	Answer whether the argument header has compiled method format */
 
 static sqInt
@@ -47718,16 +47623,6 @@
 	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)
 {
@@ -48713,6 +48608,9 @@
 	not already marked.
 	Also set the relevant bit in the classTableBitmap so that duplicate
 	entries can be eliminated.
+	And for one-way become, which can create duplicate entries in the class
+	table, make sure
+	objOop's classIndex refers to the classObj's actual classIndex.
 	Note that this is recursive, but the metaclass chain should terminate
 	quickly. 
  */
@@ -48720,19 +48618,12 @@
 static void
 markAndTraceClassOf(sqInt objOop)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    sqInt bit;
     sqInt classIndex;
     sqInt classObj;
     sqInt classTablePage;
-    sqInt majorIndex;
+    sqInt realClassIndex;
 
 	classIndex = (longAt(objOop)) & 0x3FFFFF;
-	/* begin inClassTableBitmapSet: */
-	assert((classIndex >= (firstClassIndexPun()))
-	 && (classIndex <= (classIndexMask())));
-	majorIndex = classIndex / BitsPerByte;
-	bit = 1 << (classIndex & (BitsPerByte - 1));
-	GIV(classTableBitmap)[majorIndex] = ((GIV(classTableBitmap)[majorIndex]) | bit);
 	/* begin classOrNilAtIndex: */
 	assert((classIndex <= (tagMask()))
 	 || (classIndex >= (arrayClassIndexPun())));
@@ -48743,6 +48634,13 @@
 	}
 	classObj = longAt((classTablePage + (BaseHeaderSize)) + ((classIndex & ((1 << 10) - 1)) << 2));
 l1:	/* end classOrNilAtIndex: */;
+	realClassIndex = (longAt(classObj + 4)) & 0x3FFFFF;
+	if (classIndex != realClassIndex) {
+		/* begin setClassIndexOf:to: */
+		assert(((realClassIndex >= 0) && (realClassIndex <= (classIndexMask()))));
+		flag("endianness");
+		longAtput(objOop, ((longAt(objOop)) & (~0x3FFFFF)) + realClassIndex);
+	}
 	if (!(((((usqInt) (longAt(classObj + 4))) >> 23) & 1) != 0)) {
 		setIsMarkedOfto(classObj, 1);
 		markAndTraceClassOf(classObj);
@@ -48835,9 +48733,12 @@
 	if ((format1 >= 9)
 	 && (format1 < 24)) {
 
-		/* avoid pushing non-pointer objects on the markStack */
+		/* avoid pushing non-pointer objects on the markStack. */
+		/* Avoid tracing classes of non-objects on the heap, e.g. IRC caches, Sista counters. */
 
-		markAndTraceClassOf(objOop);
+		if (((longAt(objOop)) & 0x3FFFFF) > 0x1F) {
+			markAndTraceClassOf(objOop);
+		}
 		return;
 
 	}
@@ -48986,9 +48887,12 @@
 					if ((format1 >= 9)
 					 && (format1 < 24)) {
 
-						/* avoid pushing non-pointer objects on the markStack */
+						/* avoid pushing non-pointer objects on the markStack. */
+						/* Avoid tracing classes of non-objects on the heap, e.g. IRC caches, Sista counters. */
 
-						markAndTraceClassOf(field);
+						if (((longAt(field)) & 0x3FFFFF) > 0x1F) {
+							markAndTraceClassOf(field);
+						}
 						goto l1;
 					}
 					if (format1 == 4) {
@@ -49053,9 +48957,12 @@
 					if ((format1 >= 9)
 					 && (format1 < 24)) {
 
-						/* avoid pushing non-pointer objects on the markStack */
+						/* avoid pushing non-pointer objects on the markStack. */
+						/* Avoid tracing classes of non-objects on the heap, e.g. IRC caches, Sista counters. */
 
-						markAndTraceClassOf(field);
+						if (((longAt(field)) & 0x3FFFFF) > 0x1F) {
+							markAndTraceClassOf(field);
+						}
 						goto l2;
 					}
 					if (format1 == 4) {
@@ -49162,7 +49069,6 @@
 	/* begin ensureAllMarkBitsAreZero */
 	flag("need to implement the inc GC first...");
 	assert(allObjectsUnmarked());
-	ensureAdequateClassTableBitmap();
 	/* begin initializeUnscannedEphemerons */
 	largestFree = findLargestFreeChunk();
 	sizeOfUnusedEden = (((eden()).limit)) - GIV(freeStart);
@@ -50580,6 +50486,11 @@
 	return 1;
 }
 
+
+/*	Attempt to pin objOop, which must not be immediate.
+	If the attempt succeeds answer objOop's (possibly moved) oop.
+	If the attept fails, which can only occur if there is no memory, answer 0. */
+
 sqInt
 pinObject(sqInt objOop)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
@@ -50613,14 +50524,14 @@
 			/* begin setIsPinnedOf:to: */
 			flag("endianness");
 			longAtput(objOop, (longAt(objOop)) | (1 << 30));
-			return 0;
+			return objOop;
 		}
 		if (!(someSegmentContainsPinned())) {
 			/* begin setIsPinnedOf:to: */
 			flag("endianness");
 			longAtput(objOop, (longAt(objOop)) | (1 << 30));
 			(seg->containsPinned = 1);
-			return 0;
+			return objOop;
 		}
 	}
 	/* begin cloneInOldSpaceForPinning: */
@@ -50691,40 +50602,39 @@
 		}
 	}
 	oldClone = newObj;
-	if (oldClone == 0) {
-		return PrimErrNoMemory;
-	}
-	/* 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)) {
+	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)) {
 
-		/* 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(objOop))) >> 29) & 1) != 0)) {

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list