diff --git a/src/spur32.cog.lowcode/cogit.h b/src/spur32.cog.lowcode/cogit.h index 04aa144894..13d24499d9 100644 --- a/src/spur32.cog.lowcode/cogit.h +++ b/src/spur32.cog.lowcode/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.cog.lowcode/cogitARMv5.c b/src/spur32.cog.lowcode/cogitARMv5.c index 655a2a1cad..4aab3e6c41 100644 --- a/src/spur32.cog.lowcode/cogitARMv5.c +++ b/src/spur32.cog.lowcode/cogitARMv5.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -8322,7 +8322,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8349,11 +8349,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10044,7 +10044,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10071,11 +10071,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11580,7 +11580,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -15045,7 +15045,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -15072,11 +15072,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30744,7 +30744,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -30956,7 +30956,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30983,11 +30983,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -31101,8 +31101,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -45596,7 +45596,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -45790,7 +45790,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.cog.lowcode/cogitIA32.c b/src/spur32.cog.lowcode/cogitIA32.c index bde696458c..595d4b1777 100644 --- a/src/spur32.cog.lowcode/cogitIA32.c +++ b/src/spur32.cog.lowcode/cogitIA32.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -8163,7 +8163,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8190,11 +8190,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9859,7 +9859,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9886,11 +9886,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11422,7 +11422,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -14701,7 +14701,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -14728,11 +14728,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -27566,7 +27566,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -27785,7 +27785,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -27812,11 +27812,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -27930,8 +27930,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -41376,7 +41376,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -41561,7 +41561,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.cog.lowcode/cointerp.c b/src/spur32.cog.lowcode/cointerp.c index c43535e243..7a44dea87c 100644 --- a/src/spur32.cog.lowcode/cointerp.c +++ b/src/spur32.cog.lowcode/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1067,6 +1067,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1246,6 +1247,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1281,12 +1283,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1319,6 +1323,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1363,9 +1368,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1792,8 +1797,8 @@ _iss sqInt rememberedSetSize; _iss sqInt * freeLists; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1805,12 +1810,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1838,7 +1843,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1849,6 +1853,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -2675,7 +2680,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -44694,70 +44699,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -49389,14 +49380,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -49404,32 +49397,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -51625,12 +51660,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -56252,7 +56285,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - int resultIsNegative; + sqInt resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -59854,20 +59887,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -59927,20 +59952,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -66822,6 +66839,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -71573,20 +71606,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -73789,6 +73813,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -75605,6 +75719,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -75773,6 +75977,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -77086,6 +77331,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -79706,7 +79991,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - int bridgeSpan; + sqInt bridgeSpan; sqInt clifton; usqInt segEnd; @@ -79873,63 +80158,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -79946,7 +80174,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -80127,6 +80355,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -85987,8 +86272,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -87557,10 +87842,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -90749,7 +91035,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -92364,6 +92650,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -92410,7 +92697,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog.lowcode/cointerp.h b/src/spur32.cog.lowcode/cointerp.h index ce548c105d..7afdc67bf2 100644 --- a/src/spur32.cog.lowcode/cointerp.h +++ b/src/spur32.cog.lowcode/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.cog.lowcode/gcc3x-cointerp.c b/src/spur32.cog.lowcode/gcc3x-cointerp.c index b85d761a5c..82830691b6 100644 --- a/src/spur32.cog.lowcode/gcc3x-cointerp.c +++ b/src/spur32.cog.lowcode/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1070,6 +1070,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1249,6 +1250,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1284,12 +1286,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1322,6 +1326,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1366,9 +1371,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1795,8 +1800,8 @@ _iss sqInt rememberedSetSize; _iss sqInt * freeLists; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1808,12 +1813,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1841,7 +1846,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1852,6 +1856,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -2678,7 +2683,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2829,10 +2834,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -44703,70 +44706,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -49398,14 +49387,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -49413,32 +49404,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -51634,12 +51667,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -56261,7 +56292,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - int resultIsNegative; + sqInt resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -59863,20 +59894,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -59936,20 +59959,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -66831,6 +66846,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -71582,20 +71613,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -73798,6 +73820,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -75614,6 +75726,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -75782,6 +75984,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -77095,6 +77338,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -79715,7 +79998,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - int bridgeSpan; + sqInt bridgeSpan; sqInt clifton; usqInt segEnd; @@ -79882,63 +80165,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -79955,7 +80181,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -80136,6 +80362,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -85996,8 +86279,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -87566,10 +87849,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -90758,7 +91042,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -92373,6 +92657,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -92419,7 +92704,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog.lowcode/vmCallback.h b/src/spur32.cog.lowcode/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur32.cog.lowcode/vmCallback.h +++ b/src/spur32.cog.lowcode/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur32.cog/cogit.h b/src/spur32.cog/cogit.h index b84782354e..374c67e9a1 100644 --- a/src/spur32.cog/cogit.h +++ b/src/spur32.cog/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.cog/cogitARMv5.c b/src/spur32.cog/cogitARMv5.c index 83f8a79e30..6631c8fcc9 100644 --- a/src/spur32.cog/cogitARMv5.c +++ b/src/spur32.cog/cogitARMv5.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -912,7 +912,7 @@ static sqInt genPrimitiveStringAtPut(void); static NoDbgRegParms sqInt genRemoveSmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt genShiftAwaySmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt inBytes, sqInt litCountReg, sqInt scratchReg); -static NoDbgRegParms sqInt inlineCacheTagForInstance(sqInt oop); +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop); static NoDbgRegParms AbstractInstruction * jumpNotSmallIntegerUnsignedValueInRegister(sqInt reg); static NoDbgRegParms sqInt markAndTraceCacheTagLiteralinatpc(sqInt literal, CogMethod *cogMethodOrNil, usqInt address); static sqInt numSmallIntegerBits(void); @@ -8134,7 +8134,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8161,11 +8161,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8364,7 +8364,7 @@ callCogCodePopReceiverAndClassRegs(void) static NoDbgRegParms sqInt ceCPICMissreceiver(CogMethod *cPIC, sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt errorSelectorOrNil; sqInt methodOrSelectorIndex; sqInt newTargetMethodOrNil; @@ -8508,7 +8508,7 @@ ceMalloc(size_t size) static NoDbgRegParms sqInt ceSICMiss(sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt entryPoint; sqInt errorSelectorOrNil; sqInt extent; @@ -9856,7 +9856,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9883,11 +9883,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11106,7 +11106,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -13271,7 +13271,7 @@ void linkSendAtintooffsetreceiver(sqInt callSiteReturnAddress, CogMethod *sendingMethod, CogMethod *targetMethod, sqInt theEntryOffset, sqInt receiver) { sqInt extent; - sqInt inlineCacheTag; + usqInt inlineCacheTag; assert((theEntryOffset == cmEntryOffset) || (theEntryOffset == cmNoCheckEntryOffset)); @@ -14376,7 +14376,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -14403,11 +14403,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -21773,7 +21773,7 @@ getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt c.f. getInlineCacheClassTagFrom:into: & inlineCacheTagForClass: */ /* CogObjectRepresentationFor32BitSpur>>#inlineCacheTagForInstance: */ -static NoDbgRegParms sqInt +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop) { return (isImmediate(oop) @@ -28499,7 +28499,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -28646,7 +28646,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28673,11 +28673,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28791,8 +28791,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -32771,7 +32771,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -32964,7 +32964,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.cog/cogitIA32.c b/src/spur32.cog/cogitIA32.c index 96111ec753..311c67aa68 100644 --- a/src/spur32.cog/cogitIA32.c +++ b/src/spur32.cog/cogitIA32.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7972,7 +7972,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -7999,11 +7999,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9668,7 +9668,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9695,11 +9695,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10842,7 +10842,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -13920,7 +13920,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -13947,11 +13947,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -25512,7 +25512,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -25683,7 +25683,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -25710,11 +25710,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -25828,8 +25828,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -29537,7 +29537,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -29721,7 +29721,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.cog/cointerp.c b/src/spur32.cog/cointerp.c index 023cb06895..734f3b8f0c 100644 --- a/src/spur32.cog/cointerp.c +++ b/src/spur32.cog/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1055,6 +1055,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1230,6 +1231,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1265,11 +1267,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1302,6 +1306,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1346,9 +1351,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1780,12 +1785,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1813,7 +1818,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1824,6 +1828,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -2650,7 +2655,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -26789,70 +26794,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -31472,14 +31463,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -31487,32 +31480,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32949,7 +32984,7 @@ primitiveInvokeObjectAsMethod(void) sqInt lookupClassTag; usqInt newObj; usqInt numBytes; - sqInt runArgs; + usqInt runArgs; sqInt runReceiver; char *sp; sqInt tagBits; @@ -33708,12 +33743,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -38335,7 +38368,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -41913,20 +41946,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41986,20 +42011,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -48881,6 +48898,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -53620,20 +53653,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -55800,6 +55824,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -57616,6 +57730,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -57774,6 +57978,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -59087,6 +59332,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -61874,63 +62159,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -61947,7 +62175,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -62128,6 +62356,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67955,8 +68240,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -69485,10 +69770,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -72674,7 +72960,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -74267,6 +74553,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -74313,7 +74600,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog/cointerp.h b/src/spur32.cog/cointerp.h index ff66a74cf3..0877050e23 100644 --- a/src/spur32.cog/cointerp.h +++ b/src/spur32.cog/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.cog/cointerpmt.c b/src/spur32.cog/cointerpmt.c index b40fff97ee..003e933b66 100644 --- a/src/spur32.cog/cointerpmt.c +++ b/src/spur32.cog/cointerpmt.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1155,6 +1155,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1330,6 +1331,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1365,11 +1367,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1402,6 +1406,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1446,9 +1451,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1875,12 +1880,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss CogVMThread ** threads; _iss sqInt mobileStart; @@ -1910,7 +1915,6 @@ _iss sqInt processHasThreadAffinity; _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1922,6 +1926,7 @@ _iss sqInt relinquishing; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt shrinkThreshold; _iss sqInt statTenures; @@ -2764,7 +2769,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -30627,70 +30632,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -35298,14 +35289,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -35313,32 +35306,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -37534,12 +37569,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -45639,20 +45672,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45712,20 +45737,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -52607,6 +52624,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -57366,20 +57399,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59546,6 +59570,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -61362,6 +61476,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61520,6 +61724,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -62833,6 +63078,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -65453,7 +65738,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - sqInt bridgeSpan; + int bridgeSpan; sqInt clifton; usqInt segEnd; @@ -65620,63 +65905,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -65874,6 +66102,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -69803,13 +70088,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -69821,12 +70107,13 @@ getErrorObjectFromPrimFailCode(void) ? longAt(table - BaseHeaderSize) : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -71532,8 +71819,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -72970,10 +73257,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -75857,7 +76145,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -77450,6 +77738,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -77496,7 +77785,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog/cointerpmt.h b/src/spur32.cog/cointerpmt.h index 123b5f0a30..c42dd34c02 100644 --- a/src/spur32.cog/cointerpmt.h +++ b/src/spur32.cog/cointerpmt.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.cog/gcc3x-cointerp.c b/src/spur32.cog/gcc3x-cointerp.c index 0294ccd3dd..e31649e3fa 100644 --- a/src/spur32.cog/gcc3x-cointerp.c +++ b/src/spur32.cog/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1058,6 +1058,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1233,6 +1234,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1268,11 +1270,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1305,6 +1309,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1349,9 +1354,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1783,12 +1788,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1816,7 +1821,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1827,6 +1831,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -2653,7 +2658,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2802,10 +2807,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -26798,70 +26801,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -31481,14 +31470,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -31496,32 +31487,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32958,7 +32991,7 @@ primitiveInvokeObjectAsMethod(void) sqInt lookupClassTag; usqInt newObj; usqInt numBytes; - sqInt runArgs; + usqInt runArgs; sqInt runReceiver; char *sp; sqInt tagBits; @@ -33717,12 +33750,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -38344,7 +38375,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -41922,20 +41953,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41995,20 +42018,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -48890,6 +48905,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -53629,20 +53660,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -55809,6 +55831,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -57625,6 +57737,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -57783,6 +57985,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -59096,6 +59339,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -61883,63 +62166,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -61956,7 +62182,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -62137,6 +62363,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67964,8 +68247,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -69494,10 +69777,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -72683,7 +72967,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -74276,6 +74560,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -74322,7 +74607,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog/gcc3x-cointerpmt.c b/src/spur32.cog/gcc3x-cointerpmt.c index 1660dcbeeb..c490a382ce 100644 --- a/src/spur32.cog/gcc3x-cointerpmt.c +++ b/src/spur32.cog/gcc3x-cointerpmt.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1158,6 +1158,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1333,6 +1334,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1368,11 +1370,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1405,6 +1409,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1449,9 +1454,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1878,12 +1883,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss CogVMThread ** threads; _iss sqInt mobileStart; @@ -1913,7 +1918,6 @@ _iss sqInt processHasThreadAffinity; _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1925,6 +1929,7 @@ _iss sqInt relinquishing; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt shrinkThreshold; _iss sqInt statTenures; @@ -2767,7 +2772,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2922,10 +2927,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -30636,70 +30639,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -35307,14 +35296,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -35322,32 +35313,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -37543,12 +37576,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -45648,20 +45679,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45721,20 +45744,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -52616,6 +52631,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -57375,20 +57406,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59555,6 +59577,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -61371,6 +61483,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61529,6 +61731,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -62842,6 +63085,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -65462,7 +65745,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - sqInt bridgeSpan; + int bridgeSpan; sqInt clifton; usqInt segEnd; @@ -65629,63 +65912,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -65883,6 +66109,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -69812,13 +70095,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -69830,12 +70114,13 @@ getErrorObjectFromPrimFailCode(void) ? longAt(table - BaseHeaderSize) : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -71541,8 +71826,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -72979,10 +73264,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -75866,7 +76152,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -77459,6 +77745,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -77505,7 +77792,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.cog/vmCallback.h b/src/spur32.cog/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur32.cog/vmCallback.h +++ b/src/spur32.cog/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur32.sista/cogit.h b/src/spur32.sista/cogit.h index 92252982ef..ef7ac704d0 100644 --- a/src/spur32.sista/cogit.h +++ b/src/spur32.sista/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.sista/cogitARMv5.c b/src/spur32.sista/cogitARMv5.c index 743fb7b165..40c33c14c3 100644 --- a/src/spur32.sista/cogitARMv5.c +++ b/src/spur32.sista/cogitARMv5.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -918,7 +918,7 @@ static sqInt genPrimitiveStringAtPut(void); static NoDbgRegParms sqInt genRemoveSmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt genShiftAwaySmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt inBytes, sqInt litCountReg, sqInt scratchReg); -static NoDbgRegParms sqInt inlineCacheTagForInstance(sqInt oop); +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop); static NoDbgRegParms AbstractInstruction * jumpNotSmallIntegerUnsignedValueInRegister(sqInt reg); static NoDbgRegParms sqInt markAndTraceCacheTagLiteralinatpc(sqInt literal, CogMethod *cogMethodOrNil, usqInt address); static NoDbgRegParms usqInt numCountersFor(usqInt theCounters); @@ -8248,7 +8248,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8275,11 +8275,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8505,7 +8505,7 @@ callCogCodePopReceiverAndClassRegs(void) static NoDbgRegParms sqInt ceCPICMissreceiver(CogMethod *cPIC, sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt errorSelectorOrNil; sqInt methodOrSelectorIndex; sqInt newTargetMethodOrNil; @@ -8649,7 +8649,7 @@ ceMalloc(size_t size) static NoDbgRegParms sqInt ceSICMiss(sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt entryPoint; sqInt errorSelectorOrNil; sqInt extent; @@ -10027,7 +10027,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10054,11 +10054,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11300,7 +11300,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -13310,7 +13310,7 @@ void linkSendAtintooffsetreceiver(sqInt callSiteReturnAddress, CogMethod *sendingMethod, CogMethod *targetMethod, sqInt theEntryOffset, sqInt receiver) { sqInt extent; - sqInt inlineCacheTag; + usqInt inlineCacheTag; assert((theEntryOffset == cmEntryOffset) || (theEntryOffset == cmNoCheckEntryOffset)); @@ -14455,7 +14455,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -14482,11 +14482,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -21958,7 +21958,7 @@ getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt c.f. getInlineCacheClassTagFrom:into: & inlineCacheTagForClass: */ /* CogObjectRepresentationFor32BitSpur>>#inlineCacheTagForInstance: */ -static NoDbgRegParms sqInt +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop) { return (isImmediate(oop) @@ -29481,7 +29481,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -29626,7 +29626,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29653,11 +29653,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29798,8 +29798,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -34937,7 +34937,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -35108,7 +35108,7 @@ genSpecialSelectorComparisonWithoutCounters(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -35879,7 +35879,7 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35906,11 +35906,11 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -36268,7 +36268,7 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -36295,11 +36295,11 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -39453,7 +39453,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteral(argInt)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.sista/cogitIA32.c b/src/spur32.sista/cogitIA32.c index c4fe737911..a627595b16 100644 --- a/src/spur32.sista/cogitIA32.c +++ b/src/spur32.sista/cogitIA32.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -900,7 +900,7 @@ static sqInt genPrimitiveStringAtPut(void); static NoDbgRegParms sqInt genRemoveSmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt genShiftAwaySmallIntegerTagsInScratchReg(sqInt scratchReg); static NoDbgRegParms sqInt getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt inBytes, sqInt litCountReg, sqInt scratchReg); -static NoDbgRegParms sqInt inlineCacheTagForInstance(sqInt oop); +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop); static NoDbgRegParms AbstractInstruction * jumpNotSmallIntegerUnsignedValueInRegister(sqInt reg); static NoDbgRegParms sqInt markAndTraceCacheTagLiteralinatpc(sqInt literal, CogMethod *cogMethodOrNil, usqInt address); static NoDbgRegParms usqInt numCountersFor(usqInt theCounters); @@ -8087,7 +8087,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8114,11 +8114,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8326,7 +8326,7 @@ callCogCodePopReceiverAndClassRegs(void) static NoDbgRegParms sqInt ceCPICMissreceiver(CogMethod *cPIC, sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt errorSelectorOrNil; sqInt methodOrSelectorIndex; sqInt newTargetMethodOrNil; @@ -8470,7 +8470,7 @@ ceMalloc(size_t size) static NoDbgRegParms sqInt ceSICMiss(sqInt receiver) { - sqInt cacheTag; + usqInt cacheTag; sqInt entryPoint; sqInt errorSelectorOrNil; sqInt extent; @@ -9840,7 +9840,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9867,11 +9867,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11037,7 +11037,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -12916,7 +12916,7 @@ void linkSendAtintooffsetreceiver(sqInt callSiteReturnAddress, CogMethod *sendingMethod, CogMethod *targetMethod, sqInt theEntryOffset, sqInt receiver) { sqInt extent; - sqInt inlineCacheTag; + usqInt inlineCacheTag; assert((theEntryOffset == cmEntryOffset) || (theEntryOffset == cmNoCheckEntryOffset)); @@ -14046,7 +14046,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -14073,11 +14073,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -20723,7 +20723,7 @@ getLiteralCountOfplusOneinBytesintoscratch(sqInt methodReg, sqInt plusOne, sqInt c.f. getInlineCacheClassTagFrom:into: & inlineCacheTagForClass: */ /* CogObjectRepresentationFor32BitSpur>>#inlineCacheTagForInstance: */ -static NoDbgRegParms sqInt +static NoDbgRegParms usqInt inlineCacheTagForInstance(sqInt oop) { return (isImmediate(oop) @@ -26437,7 +26437,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -26606,7 +26606,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -26633,11 +26633,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -26778,8 +26778,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -31539,7 +31539,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -31701,7 +31701,7 @@ genSpecialSelectorComparisonWithoutCounters(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -32410,7 +32410,7 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32437,11 +32437,11 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32799,7 +32799,7 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32826,11 +32826,11 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35762,7 +35762,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur32.sista/cointerp.c b/src/spur32.sista/cointerp.c index 7ea97d2f32..2bd2017a4b 100644 --- a/src/spur32.sista/cointerp.c +++ b/src/spur32.sista/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1065,6 +1065,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1244,6 +1245,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1279,12 +1281,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1317,6 +1321,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1361,9 +1366,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1783,8 +1788,8 @@ _iss sqInt rememberedSetSize; _iss sqInt * freeLists; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1796,12 +1801,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1829,7 +1834,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1840,6 +1844,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1992,7 +1997,7 @@ static signed short primitiveMetadataTable[MaxPrimitiveIndex + 2 /* 584 */] = { /*78*/ 0, 0, /*80*/ -256,-256,-256, 4, 4, 0, 0x100, 0, 0x200,-256,-256, 0, 0, 0, 0x100,-256, 0,-256, /*98*/ 0, 0, -/*100*/ 260, 0x200, 0x100, 0x200,-256, 513,-256,-256,-256,-256, 0, 0x100, 0, 0,-256, +/*100*/ 260, 0x200, 0x200, 0x200,-256, 513,-256,-256,-256,-256, 0, 0x100, 0, 0,-256, /*115*/ 0x100, 0, 12, 260, 0, /*120*/ 524, 0x100,-256,-256, 1, 0, 0, 0, 0,-255,-256, 0, 0, 0, 0,-256, 0,-256,-256, /*139*/ 0, @@ -2666,7 +2671,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -30002,70 +30007,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34697,14 +34688,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34712,32 +34705,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -36933,12 +36968,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -41560,7 +41593,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -44377,9 +44410,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; return 0; @@ -45011,9 +45044,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; } @@ -45162,20 +45195,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45235,20 +45260,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45260,9 +45277,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + ephemeronCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -45335,9 +45352,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + weakCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } GIV(weakList) = null; } @@ -52130,6 +52147,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -56881,20 +56914,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59097,6 +59121,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -60913,6 +61027,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61081,6 +61285,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -62394,6 +62639,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -65014,7 +65299,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - sqInt bridgeSpan; + int bridgeSpan; sqInt clifton; usqInt segEnd; @@ -65181,63 +65466,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -65435,6 +65663,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -71281,8 +71566,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -72811,10 +73096,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -76003,7 +76289,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -77596,6 +77882,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -77642,7 +77929,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.sista/cointerp.h b/src/spur32.sista/cointerp.h index 28d92a35c1..dc0d8df092 100644 --- a/src/spur32.sista/cointerp.h +++ b/src/spur32.sista/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur32.sista/gcc3x-cointerp.c b/src/spur32.sista/gcc3x-cointerp.c index b449a1047a..d1584987f4 100644 --- a/src/spur32.sista/gcc3x-cointerp.c +++ b/src/spur32.sista/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1068,6 +1068,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1247,6 +1248,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1282,12 +1284,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1320,6 +1324,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1364,9 +1369,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1786,8 +1791,8 @@ _iss sqInt rememberedSetSize; _iss sqInt * freeLists; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1799,12 +1804,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1832,7 +1837,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1843,6 +1847,7 @@ _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss usqInt cogCodeSize; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1995,7 +2000,7 @@ static signed short primitiveMetadataTable[MaxPrimitiveIndex + 2 /* 584 */] = { /*78*/ 0, 0, /*80*/ -256,-256,-256, 4, 4, 0, 0x100, 0, 0x200,-256,-256, 0, 0, 0, 0x100,-256, 0,-256, /*98*/ 0, 0, -/*100*/ 260, 0x200, 0x100, 0x200,-256, 513,-256,-256,-256,-256, 0, 0x100, 0, 0,-256, +/*100*/ 260, 0x200, 0x200, 0x200,-256, 513,-256,-256,-256,-256, 0, 0x100, 0, 0,-256, /*115*/ 0x100, 0, 12, 260, 0, /*120*/ 524, 0x100,-256,-256, 1, 0, 0, 0, 0,-255,-256, 0, 0, 0, 0,-256, 0,-256,-256, /*139*/ 0, @@ -2669,7 +2674,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2818,10 +2823,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -30011,70 +30014,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34706,14 +34695,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34721,32 +34712,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -36942,12 +36975,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -41569,7 +41600,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -44386,9 +44417,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; return 0; @@ -45020,9 +45051,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; } @@ -45171,20 +45202,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45244,20 +45267,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45269,9 +45284,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + ephemeronCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -45344,9 +45359,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + weakCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } GIV(weakList) = null; } @@ -52139,6 +52154,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -56890,20 +56921,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59106,6 +59128,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -60922,6 +61034,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61090,6 +61292,47 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -62403,6 +62646,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -65023,7 +65306,7 @@ bridgeFor(SpurSegmentInfo *aSegment) static NoDbgRegParms void bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil) { - sqInt bridgeSpan; + int bridgeSpan; sqInt clifton; usqInt segEnd; @@ -65190,63 +65473,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -65444,6 +65670,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -71290,8 +71573,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -72820,10 +73103,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -76012,7 +76296,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -77605,6 +77889,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -77651,7 +77936,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.sista/vmCallback.h b/src/spur32.sista/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur32.sista/vmCallback.h +++ b/src/spur32.sista/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur32.stack.lowcode/gcc3x-interp.c b/src/spur32.stack.lowcode/gcc3x-interp.c index 9ee3732ed3..68262cf7d0 100644 --- a/src/spur32.stack.lowcode/gcc3x-interp.c +++ b/src/spur32.stack.lowcode/gcc3x-interp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -766,6 +766,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -949,6 +950,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -984,11 +986,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1021,6 +1025,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1066,9 +1071,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1561,9 +1566,9 @@ _iss char * nativeStackPointer; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1591,7 +1596,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1601,6 +1605,7 @@ _iss sqInt savedFirstFieldsSpaceNotInOldSpace; _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1748,7 +1753,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2389,7 +2394,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2501,10 +2506,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -26422,70 +26425,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -30385,14 +30374,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -30400,32 +30391,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32715,12 +32748,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -40941,20 +40972,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41014,20 +41037,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -47850,6 +47865,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -52731,20 +52762,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -54961,6 +54983,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -56771,6 +56883,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -56880,6 +57082,47 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -58209,6 +58452,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -60974,63 +61257,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -61228,6 +61454,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67526,8 +67809,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -69317,10 +69600,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -73322,7 +73606,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -75162,6 +75446,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -75208,7 +75493,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.stack.lowcode/interp.c b/src/spur32.stack.lowcode/interp.c index 94125a12f5..873c7652d2 100644 --- a/src/spur32.stack.lowcode/interp.c +++ b/src/spur32.stack.lowcode/interp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -763,6 +763,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -946,6 +947,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -981,11 +983,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms int rawClassTagForClass(sqInt classObj); extern int rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1018,6 +1022,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1063,9 +1068,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1558,9 +1563,9 @@ _iss char * nativeStackPointer; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1588,7 +1593,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1598,6 +1602,7 @@ _iss sqInt savedFirstFieldsSpaceNotInOldSpace; _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1745,7 +1750,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2386,7 +2391,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -26413,70 +26418,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -30376,14 +30367,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -30391,32 +30384,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32706,12 +32741,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -40932,20 +40965,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41005,20 +41030,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -47841,6 +47858,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -52722,20 +52755,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -54952,6 +54976,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -56762,6 +56876,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -56871,6 +57075,47 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -58200,6 +58445,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -60965,63 +61250,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -61219,6 +61447,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67517,8 +67802,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -69308,10 +69593,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -73313,7 +73599,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -75153,6 +75439,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -75199,7 +75486,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.stack.lowcode/vmCallback.h b/src/spur32.stack.lowcode/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur32.stack.lowcode/vmCallback.h +++ b/src/spur32.stack.lowcode/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur32.stack/gcc3x-interp.c b/src/spur32.stack/gcc3x-interp.c index e653947c48..665f4ad556 100644 --- a/src/spur32.stack/gcc3x-interp.c +++ b/src/spur32.stack/gcc3x-interp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -761,6 +761,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -940,6 +941,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -975,10 +977,12 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1011,6 +1015,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1056,9 +1061,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1535,9 +1540,9 @@ _iss usqInt totalHeapSizeIncludingBridges; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1565,7 +1570,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1575,6 +1579,7 @@ _iss sqInt savedFirstFieldsSpaceNotInOldSpace; _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1722,7 +1727,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2363,7 +2368,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2473,10 +2478,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -13560,70 +13563,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -17523,14 +17512,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -17538,32 +17529,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -19853,12 +19886,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -28072,20 +28103,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -28145,20 +28168,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -34981,6 +34996,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -39850,20 +39881,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -42044,6 +42066,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -43854,6 +43966,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -43953,6 +44155,47 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -45282,6 +45525,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -48047,63 +48330,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -48301,6 +48527,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -54565,8 +54848,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -56323,10 +56606,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -60267,7 +60551,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -62065,6 +62349,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -62111,7 +62396,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.stack/interp.c b/src/spur32.stack/interp.c index 0dbc03988f..114cdc2dd0 100644 --- a/src/spur32.stack/interp.c +++ b/src/spur32.stack/interp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -758,6 +758,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -937,6 +938,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -972,10 +974,12 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern int rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1008,6 +1012,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); extern sqInt unpinObject(sqInt objOop); @@ -1053,9 +1058,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1532,9 +1537,9 @@ _iss usqInt totalHeapSizeIncludingBridges; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1562,7 +1567,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1572,6 +1576,7 @@ _iss sqInt savedFirstFieldsSpaceNotInOldSpace; _iss sqInt highestRunnableProcessPriority; _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss sqInt statTenures; _iss sqInt weakList; @@ -1719,7 +1724,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2360,7 +2365,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -13551,70 +13556,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (4 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -17514,14 +17505,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -17529,32 +17522,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? longAt(obj - BaseHeaderSize) + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -19844,12 +19879,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -28063,20 +28096,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -28136,20 +28161,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -34972,6 +34989,22 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(ephemeron, ((longAt(ephemeron)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -39841,20 +39874,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - flag("endianness"); - longAtput(longAt(p), ((longAt(longAt(p))) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -42035,6 +42059,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -43845,6 +43959,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -43944,6 +44148,47 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -45273,6 +45518,46 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + flag("endianness"); + longAtput(mourner, ((longAt(mourner)) & ((unsigned int)~(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -48038,63 +48323,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -48292,6 +48520,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -54556,8 +54841,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -56314,10 +56599,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((methodHeader & 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -60258,7 +60544,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((methodHeader & 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((int) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -62056,6 +62342,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -62102,7 +62389,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur32.stack/validImage.c b/src/spur32.stack/validImage.c index ac27490610..ee5fd70cf1 100644 --- a/src/spur32.stack/validImage.c +++ b/src/spur32.stack/validImage.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - ImageLeakChecker VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + ImageLeakChecker VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "ImageLeakChecker VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "ImageLeakChecker VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -239,6 +239,7 @@ typedef struct _StackPage { # define NeverInline /*empty*/ #endif +extern NeverInline void eekcr(void); static NoDbgRegParms sqInt growOldSpaceByAtLeast(sqInt minAmmount); static NoDbgRegParms void initializeInterpreter(sqInt bytesToShift); extern void * ioLoadFunctionFrom(char *functionName, char *moduleName); @@ -554,6 +555,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -589,6 +591,7 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); extern int rawHashBitsOf(sqInt objOop); @@ -664,7 +667,6 @@ static void checkAssumedCompactClasses(void); extern sqInt checkImageHeaderFromBytesAndSize(char *bytes, sqInt totalSize); static NoDbgRegParms sqInt checkImageVersionFromstartingAtassignRawVersion(sqImageFile f, squeakFileOffsetType imageOffset, sqInt *rawVersionPtr); static sqInt convertFloatsToPlatformOrder(void); -extern NeverInline void eekcr(void); static sqInt elementsPerPrintOopLine(void); static NoDbgRegParms void ensureImageFormatIsUpToDate(sqInt swapBytes); static NoDbgRegParms sqInt fetchStackPointerOf(sqInt aContext); @@ -750,8 +752,8 @@ _iss FILE * transcript; _iss sqInt specialObjectsOop; _iss sqInt * freeLists; _iss usqInt freeListsMask; -_iss sqInt markStack; _iss sqInt numClassTablePages; +_iss sqInt markStack; _iss sqInt hiddenRootsObj; _iss sqInt numSegments; _iss SpurSegmentInfo * segments; @@ -771,8 +773,8 @@ _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; _iss usqInt newSpaceStart; _iss sqInt numSegInfos; -_iss sqInt mournQueue; _iss sqInt verbose; +_iss sqInt mournQueue; _iss sqInt classTableFirstPage; _iss sqInt falseObj; _iss sqInt rememberedSetLimit; @@ -997,7 +999,7 @@ sqInt extraVMMemory; sqInt ffiExceptionResponse; sqInt inIOProcessEvents; struct VirtualMachine* interpreterProxy; -const char *interpreterVersion = "Open Smalltalk ImageChecker VM [ImageLeakChecker VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk ImageChecker VM [ImageLeakChecker VMMaker.oscog-eem.3482]"; usqInt maxOldSpaceSize; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; @@ -1067,6 +1069,18 @@ int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); /*** Methods ***/ + +/* For marking the end of a leak check print message */ + + /* ImageLeakChecker>>#eekcr */ +NeverInline void +eekcr(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + if (GIV(verbose)) { + printf("\n"); + } +} + /* ImageLeakChecker>>#growOldSpaceByAtLeast: */ static NoDbgRegParms sqInt growOldSpaceByAtLeast(sqInt minAmmount) @@ -9026,6 +9040,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + usqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + /* begin startAddressForBridgedHeapEnumeration */ + if (GIV(pastSpaceStart) > (((GIV(pastSpace)).start))) { + address = ((GIV(pastSpace)).start); + } + else { + if (GIV(freeStart) > (((GIV(eden)).start))) { + address = ((GIV(eden)).start); + } + else { + address = GIV(oldSpaceStart); + } + } + startObject = objectStartingAt(address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = classIndexOf(obj); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = formatOf(obj); + if (format == (ephemeronFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -10748,6 +10852,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + usqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + /* begin startAddressForBridgedHeapEnumeration */ + if (GIV(pastSpaceStart) > (((GIV(pastSpace)).start))) { + address = ((GIV(pastSpace)).start); + } + else { + if (GIV(freeStart) > (((GIV(eden)).start))) { + address = ((GIV(eden)).start); + } + else { + address = GIV(oldSpaceStart); + } + } + startObject = objectStartingAt(address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = classIndexOf(obj); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = formatOf(obj); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress + 4); + obj = ((((usqInt)(followingWord)) >> (numSlotsHalfShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && (1 == (longAt(followingWordAddress))) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -12511,16 +12705,6 @@ convertFloatsToPlatformOrder(void) return 0; } - -/* For marking the end of a leak check print message */ - - /* StackInterpreter>>#eekcr */ -NeverInline void -eekcr(void) -{ - printf("\n"); -} - /* StackInterpreter>>#elementsPerPrintOopLine */ static sqInt elementsPerPrintOopLine(void) @@ -13209,8 +13393,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((int) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } diff --git a/src/spur32.stack/vmCallback.h b/src/spur32.stack/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur32.stack/vmCallback.h +++ b/src/spur32.stack/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur64.cog.lowcode/cogit.h b/src/spur64.cog.lowcode/cogit.h index 04aa144894..13d24499d9 100644 --- a/src/spur64.cog.lowcode/cogit.h +++ b/src/spur64.cog.lowcode/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.cog.lowcode/cogitARMv8.c b/src/spur64.cog.lowcode/cogitARMv8.c index 4c13b636b5..44f1e03ce4 100644 --- a/src/spur64.cog.lowcode/cogitARMv8.c +++ b/src/spur64.cog.lowcode/cogitARMv8.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7605,7 +7605,7 @@ rewriteImm19JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqIn static NoDbgRegParms sqInt rewriteImm26JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqInt followingAddress, sqInt targetAddress) { - sqInt instrOpcode; + unsigned int instrOpcode; sqInt mcpc; sqInt offset; @@ -8556,7 +8556,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8583,11 +8583,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10495,7 +10495,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10522,11 +10522,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11860,7 +11860,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -15848,7 +15848,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -15875,11 +15875,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -33196,7 +33196,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -33434,7 +33434,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -33461,11 +33461,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -33580,8 +33580,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -46903,7 +46903,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -47097,7 +47097,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog.lowcode/cogitX64SysV.c b/src/spur64.cog.lowcode/cogitX64SysV.c index 843d9425b6..be954e3f9f 100644 --- a/src/spur64.cog.lowcode/cogitX64SysV.c +++ b/src/spur64.cog.lowcode/cogitX64SysV.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -3870,7 +3870,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3897,11 +3897,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5573,7 +5573,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5600,11 +5600,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -7087,7 +7087,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -10406,7 +10406,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10433,11 +10433,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30071,7 +30071,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -30296,7 +30296,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30323,11 +30323,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30442,8 +30442,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -43004,7 +43004,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -43189,7 +43189,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog.lowcode/cogitX64WIN64.c b/src/spur64.cog.lowcode/cogitX64WIN64.c index 561db48ee3..fa47e1e306 100644 --- a/src/spur64.cog.lowcode/cogitX64WIN64.c +++ b/src/spur64.cog.lowcode/cogitX64WIN64.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3471 uuid: c3abaac1-cda5-44ec-81c1-55154ab54aef " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -3870,7 +3870,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3897,11 +3897,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5573,7 +5573,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5600,11 +5600,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -7108,7 +7108,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -10435,7 +10435,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10462,11 +10462,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30135,7 +30135,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -30368,7 +30368,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30395,11 +30395,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -30514,8 +30514,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -43076,7 +43076,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -43261,7 +43261,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog.lowcode/cointerp.c b/src/spur64.cog.lowcode/cointerp.c index 6da925ca64..728cbd6dbb 100644 --- a/src/spur64.cog.lowcode/cointerp.c +++ b/src/spur64.cog.lowcode/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1091,6 +1091,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1271,6 +1272,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1306,12 +1308,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1344,6 +1348,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1390,9 +1395,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1830,12 +1835,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1863,7 +1868,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1882,6 +1886,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2696,7 +2701,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -44137,70 +44142,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -48797,14 +48788,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -48812,32 +48805,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -50164,7 +50199,7 @@ primitiveInvokeObjectAsMethod(void) sqInt lookupClassTag; usqInt newObj; usqInt numBytes; - usqInt runArgs; + sqInt runArgs; sqInt runReceiver; char *sp; sqInt tagBits; @@ -50179,7 +50214,7 @@ primitiveInvokeObjectAsMethod(void) /* begin allocateNewSpaceSlots:format:classIndex: */ if (GIV(argumentCount) >= (numSlotsMask())) { if (GIV(argumentCount) > 0xFFFFFFFFU) { - runArgs = null; + runArgs = ((usqInt) null); goto l1; } newObj = GIV(freeStart) + BaseHeaderSize; @@ -50941,12 +50976,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -59582,9 +59615,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; return 0; @@ -60218,9 +60251,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; } @@ -60369,19 +60402,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -60441,19 +60467,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -60465,9 +60484,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + ephemeronCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -60540,9 +60559,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + weakCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } GIV(weakList) = null; } @@ -67413,6 +67432,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -72238,19 +72272,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -74473,6 +74499,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -76297,6 +76413,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -76469,6 +76675,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -77792,6 +78038,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -80668,63 +80953,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -80741,7 +80969,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - usqInt node; + sqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -80922,6 +81150,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -86767,8 +87052,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -88301,10 +88586,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -91597,7 +91883,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -93212,6 +93498,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -93258,7 +93545,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog.lowcode/cointerp.h b/src/spur64.cog.lowcode/cointerp.h index 82fdb4daa7..941b98cc4d 100644 --- a/src/spur64.cog.lowcode/cointerp.h +++ b/src/spur64.cog.lowcode/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.cog.lowcode/gcc3x-cointerp.c b/src/spur64.cog.lowcode/gcc3x-cointerp.c index 0898d72db7..34f4c294cf 100644 --- a/src/spur64.cog.lowcode/gcc3x-cointerp.c +++ b/src/spur64.cog.lowcode/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1094,6 +1094,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1274,6 +1275,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1309,12 +1311,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1347,6 +1351,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1393,9 +1398,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1833,12 +1838,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1866,7 +1871,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1885,6 +1889,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2699,7 +2704,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -2857,10 +2862,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -44146,70 +44149,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -48806,14 +48795,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -48821,32 +48812,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -50173,7 +50206,7 @@ primitiveInvokeObjectAsMethod(void) sqInt lookupClassTag; usqInt newObj; usqInt numBytes; - usqInt runArgs; + sqInt runArgs; sqInt runReceiver; char *sp; sqInt tagBits; @@ -50188,7 +50221,7 @@ primitiveInvokeObjectAsMethod(void) /* begin allocateNewSpaceSlots:format:classIndex: */ if (GIV(argumentCount) >= (numSlotsMask())) { if (GIV(argumentCount) > 0xFFFFFFFFU) { - runArgs = null; + runArgs = ((usqInt) null); goto l1; } newObj = GIV(freeStart) + BaseHeaderSize; @@ -50950,12 +50983,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -59591,9 +59622,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; return 0; @@ -60227,9 +60258,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; } @@ -60378,19 +60409,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -60450,19 +60474,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -60474,9 +60491,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + ephemeronCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -60549,9 +60566,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + weakCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } GIV(weakList) = null; } @@ -67422,6 +67439,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -72247,19 +72279,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -74482,6 +74506,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -76306,6 +76420,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -76478,6 +76682,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -77801,6 +78045,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -80677,63 +80960,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -80750,7 +80976,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - usqInt node; + sqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -80931,6 +81157,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -86776,8 +87059,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -88310,10 +88593,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -91606,7 +91890,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -93221,6 +93505,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -93267,7 +93552,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog.lowcode/vmCallback.h b/src/spur64.cog.lowcode/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur64.cog.lowcode/vmCallback.h +++ b/src/spur64.cog.lowcode/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur64.cog/cogit.h b/src/spur64.cog/cogit.h index b84782354e..374c67e9a1 100644 --- a/src/spur64.cog/cogit.h +++ b/src/spur64.cog/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.cog/cogitARMv8.c b/src/spur64.cog/cogitARMv8.c index 32108687e7..833de4cbeb 100644 --- a/src/spur64.cog/cogitARMv8.c +++ b/src/spur64.cog/cogitARMv8.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7433,7 +7433,7 @@ rewriteImm19JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqIn static NoDbgRegParms sqInt rewriteImm26JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqInt followingAddress, sqInt targetAddress) { - sqInt instrOpcode; + unsigned int instrOpcode; sqInt mcpc; sqInt offset; @@ -8384,7 +8384,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8411,11 +8411,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10323,7 +10323,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10350,11 +10350,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11587,7 +11587,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -15432,7 +15432,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -15459,11 +15459,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -31406,7 +31406,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -31579,7 +31579,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -31606,11 +31606,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -31725,8 +31725,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -35712,7 +35712,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -35905,7 +35905,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog/cogitX64SysV.c b/src/spur64.cog/cogitX64SysV.c index 98046214d8..6a1213e3be 100644 --- a/src/spur64.cog/cogitX64SysV.c +++ b/src/spur64.cog/cogitX64SysV.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -1011,7 +1011,7 @@ static NoDbgRegParms sqInt genSaveRegs(AbstractInstruction *self_in_CogX64Compil static NoDbgRegParms AbstractInstruction * genSubstituteReturnAddress(AbstractInstruction *self_in_CogX64Compiler, sqInt retpc); static NoDbgRegParms AbstractInstruction * genSwapRRScratch(AbstractInstruction *self_in_CogX64Compiler, sqInt regA, sqInt regB, sqInt regTmp); static NoDbgRegParms sqInt hasVarBaseRegister(AbstractInstruction *self_in_CogX64Compiler); -static NoDbgRegParms sqInt instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); +static NoDbgRegParms int instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); static NoDbgRegParms int is32BitSignedImmediate(AbstractInstruction *self_in_CogX64Compiler, sqInt a64BitUnsignedOperand); static NoDbgRegParms int isCallPrecedingReturnPC(AbstractInstruction *self_in_CogX64Compiler, sqInt mcpc); static NoDbgRegParms sqInt isJumpAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); @@ -3712,7 +3712,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3739,11 +3739,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5415,7 +5415,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5442,11 +5442,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -6648,7 +6648,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -9804,7 +9804,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9831,11 +9831,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -25601,7 +25601,7 @@ hasVarBaseRegister(AbstractInstruction *self_in_CogX64Compiler) occur within a larger method. This is very far from a full decode. */ /* CogX64Compiler>>#instructionSizeAt: */ -static NoDbgRegParms sqInt +static NoDbgRegParms int instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc) { sqInt op; @@ -25794,7 +25794,7 @@ jumpTargetPCAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc) { sqInt byte; sqInt offset; - sqInt size; + int size; size = instructionSizeAt(self_in_CogX64Compiler, pc); if (size == 2) { @@ -28362,7 +28362,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -28539,7 +28539,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28566,11 +28566,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28685,8 +28685,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -32421,7 +32421,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -32605,7 +32605,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog/cogitX64WIN64.c b/src/spur64.cog/cogitX64WIN64.c index 3b218e6063..cb8854d3ad 100644 --- a/src/spur64.cog/cogitX64WIN64.c +++ b/src/spur64.cog/cogitX64WIN64.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -3712,7 +3712,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3739,11 +3739,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5415,7 +5415,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5442,11 +5442,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -6655,7 +6655,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -9819,7 +9819,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9846,11 +9846,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28412,7 +28412,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -28597,7 +28597,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28624,11 +28624,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -28743,8 +28743,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -32479,7 +32479,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -32663,7 +32663,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.cog/cointerp.c b/src/spur64.cog/cointerp.c index 97bc3187a1..864894dbe1 100644 --- a/src/spur64.cog/cointerp.c +++ b/src/spur64.cog/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1079,6 +1079,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1255,6 +1256,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1290,11 +1292,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1327,6 +1331,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1373,9 +1378,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1793,8 +1798,8 @@ _iss sqInt * freeLists; _iss sqInt rememberedSetSize; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1806,12 +1811,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1839,7 +1844,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1858,6 +1862,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2672,7 +2677,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -26497,70 +26502,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -31145,14 +31136,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -31160,32 +31153,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -33289,12 +33324,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -38984,7 +39017,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -41906,9 +41939,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; return 0; @@ -42542,9 +42575,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; } @@ -42693,19 +42726,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -42765,19 +42791,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -42789,9 +42808,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + ephemeronCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -42864,9 +42883,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + weakCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } GIV(weakList) = null; } @@ -49737,6 +49756,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -54550,19 +54584,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -56749,6 +56775,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -58573,6 +58689,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -58735,6 +58941,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -60058,6 +60304,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -62934,63 +63219,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -63007,7 +63235,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -63188,6 +63416,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67246,13 +67531,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -67264,12 +67550,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -69000,8 +69287,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -70520,10 +70807,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -73813,7 +74101,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -75406,6 +75694,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -75452,7 +75741,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog/cointerp.h b/src/spur64.cog/cointerp.h index 3e3b586912..d14db4b7f1 100644 --- a/src/spur64.cog/cointerp.h +++ b/src/spur64.cog/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.cog/cointerpmt.c b/src/spur64.cog/cointerpmt.c index 82b9f3a4a2..fd17d36e9a 100644 --- a/src/spur64.cog/cointerpmt.c +++ b/src/spur64.cog/cointerpmt.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1179,6 +1179,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1355,6 +1356,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1390,11 +1392,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1427,6 +1431,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1473,9 +1478,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1887,8 +1892,8 @@ _iss sqInt * freeLists; _iss sqInt rememberedSetSize; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss StackPage * mostRecentlyUsedPage; _iss sqInt remapBufferCount; @@ -1901,12 +1906,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss CogVMThread ** threads; _iss sqInt mobileStart; @@ -1936,7 +1941,6 @@ _iss sqInt processHasThreadAffinity; _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1956,6 +1960,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; @@ -2786,7 +2791,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -30335,70 +30340,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34971,14 +34962,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34986,32 +34979,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -37115,12 +37150,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -42697,7 +42730,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -45632,9 +45665,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; return 0; @@ -46268,9 +46301,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; } @@ -46419,19 +46452,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -46491,19 +46517,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -46515,9 +46534,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + ephemeronCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -46590,9 +46609,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + weakCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } GIV(weakList) = null; } @@ -53463,6 +53482,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -58296,19 +58330,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -60495,6 +60521,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -62319,6 +62435,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -62481,6 +62687,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -63804,6 +64050,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -66680,63 +66965,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -66934,6 +67162,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -70847,13 +71132,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -70865,12 +71151,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -72577,8 +72864,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -74005,10 +74292,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -76996,7 +77284,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -78589,6 +78877,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -78635,7 +78924,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog/cointerpmt.h b/src/spur64.cog/cointerpmt.h index 1de52a63a6..415b420743 100644 --- a/src/spur64.cog/cointerpmt.h +++ b/src/spur64.cog/cointerpmt.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.cog/gcc3x-cointerp.c b/src/spur64.cog/gcc3x-cointerp.c index e7ec09c552..b59568616f 100644 --- a/src/spur64.cog/gcc3x-cointerp.c +++ b/src/spur64.cog/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1082,6 +1082,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1258,6 +1259,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1293,11 +1295,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1330,6 +1334,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1376,9 +1381,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1796,8 +1801,8 @@ _iss sqInt * freeLists; _iss sqInt rememberedSetSize; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss sqInt remapBufferCount; _iss usqInt firstFreeObject; @@ -1809,12 +1814,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1842,7 +1847,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1861,6 +1865,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2675,7 +2680,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -2831,10 +2836,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -26506,70 +26509,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -31154,14 +31143,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -31169,32 +31160,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -33298,12 +33331,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -38993,7 +39024,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -41915,9 +41946,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; return 0; @@ -42551,9 +42582,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + corpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } return 0; } @@ -42702,19 +42733,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -42774,19 +42798,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -42798,9 +42815,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + ephemeronCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -42873,9 +42890,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = (listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0); + weakCorpse = ((sqInt) ((listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0))); } GIV(weakList) = null; } @@ -49746,6 +49763,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -54559,19 +54591,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -56758,6 +56782,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -58582,6 +58696,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -58744,6 +58948,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -60067,6 +60311,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -62943,63 +63226,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -63016,7 +63242,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -63197,6 +63423,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -67255,13 +67538,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -67273,12 +67557,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -69009,8 +69294,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -70529,10 +70814,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -73822,7 +74108,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -75415,6 +75701,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -75461,7 +75748,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog/gcc3x-cointerpmt.c b/src/spur64.cog/gcc3x-cointerpmt.c index d13d3b20c2..cc55240056 100644 --- a/src/spur64.cog/gcc3x-cointerpmt.c +++ b/src/spur64.cog/gcc3x-cointerpmt.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreterMT VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1182,6 +1182,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1358,6 +1359,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1393,11 +1395,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1430,6 +1434,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1476,9 +1481,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1890,8 +1895,8 @@ _iss sqInt * freeLists; _iss sqInt rememberedSetSize; _iss sqInt markStack; _iss sqInt weaklingStack; -_iss sqInt classTableFirstPage; _iss sqInt numClassTablePages; +_iss sqInt classTableFirstPage; _iss sqInt * rememberedSet; _iss StackPage * mostRecentlyUsedPage; _iss sqInt remapBufferCount; @@ -1904,12 +1909,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss CogVMThread ** threads; _iss sqInt mobileStart; @@ -1939,7 +1944,6 @@ _iss sqInt processHasThreadAffinity; _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1959,6 +1963,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; @@ -2789,7 +2794,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog MT VM [CoInterpreterMT VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -2951,10 +2956,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -30344,70 +30347,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34980,14 +34969,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34995,32 +34986,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -37124,12 +37157,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -42706,7 +42737,7 @@ primitiveSubtractLargeIntegers(void) sqInt oopRcvr; sqInt oopResult; usqLong result; - sqInt resultIsNegative; + int resultIsNegative; char *sp; oopArg = longAt(GIV(stackPointer)); @@ -45641,9 +45672,9 @@ allWeakSurvivorsOnWeakList(void) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; return 0; @@ -46277,9 +46308,9 @@ isonWeaklingList(sqInt oop, sqInt listHead) /* begin nextCorpseOrNil: */ assert(isYoung(corpse)); listOffset = ((((usqInt)(((long32At(corpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(corpse)))) >> (formatShift())) & (formatMask())); - corpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + corpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } return 0; } @@ -46428,19 +46459,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -46500,19 +46524,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -46524,9 +46541,9 @@ processEphemerons(void) /* begin nextCorpseOrNil: */ assert(isYoung(ephemeronCorpse)); listOffset = ((((usqInt)(((long32At(ephemeronCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(ephemeronCorpse)))) >> (formatShift())) & (formatMask())); - ephemeronCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + ephemeronCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } /* end fireEphemeronsOnEphemeronList */ l1:; @@ -46599,9 +46616,9 @@ processWeaklings(void) /* begin nextCorpseOrNil: */ assert(isYoung(weakCorpse)); listOffset = ((((usqInt)(((long32At(weakCorpse + 4)) & (identityHashHalfWordMask()))) << (formatFieldWidthShift())))) + ((((usqInt)((longAt(weakCorpse)))) >> (formatShift())) & (formatMask())); - weakCorpse = ((sqInt) ((listOffset - ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) - : 0))); + weakCorpse = (listOffset + ? ((((usqInt)((listOffset - 1)) << 3 /* shiftForAllocationUnit */))) + GIV(newSpaceStart) + : 0); } GIV(weakList) = null; } @@ -53472,6 +53489,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -58305,19 +58337,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -60504,6 +60528,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -62328,6 +62442,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -62490,6 +62694,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -63813,6 +64057,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -66689,63 +66972,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -66943,6 +67169,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -70856,13 +71139,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -70874,12 +71158,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -72586,8 +72871,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -74014,10 +74299,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -77005,7 +77291,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -78598,6 +78884,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -78644,7 +78931,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.cog/vmCallback.h b/src/spur64.cog/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur64.cog/vmCallback.h +++ b/src/spur64.cog/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur64.sista/cogit.h b/src/spur64.sista/cogit.h index 92252982ef..ef7ac704d0 100644 --- a/src/spur64.sista/cogit.h +++ b/src/spur64.sista/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.sista/cogitARMv8.c b/src/spur64.sista/cogitARMv8.c index 01e8c2d068..dd5bf75eae 100644 --- a/src/spur64.sista/cogitARMv8.c +++ b/src/spur64.sista/cogitARMv8.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7539,7 +7539,7 @@ rewriteImm19JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqIn static NoDbgRegParms sqInt rewriteImm26JumpBeforetarget(AbstractInstruction *self_in_CogARMv8Compiler, sqInt followingAddress, sqInt targetAddress) { - unsigned int instrOpcode; + sqInt instrOpcode; sqInt mcpc; sqInt offset; @@ -8505,7 +8505,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -8532,11 +8532,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10501,7 +10501,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -10528,11 +10528,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -11788,7 +11788,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -15399,7 +15399,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -15426,11 +15426,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32419,7 +32419,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -32590,7 +32590,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32617,11 +32617,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -32763,8 +32763,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -37912,7 +37912,7 @@ genSpecialSelectorComparison(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -38083,7 +38083,7 @@ genSpecialSelectorComparisonWithoutCounters(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -38967,7 +38967,7 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -38994,11 +38994,11 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -39357,7 +39357,7 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -39384,11 +39384,11 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -42543,7 +42543,7 @@ genSpecialSelectorArithmetic(void) (anInstruction->dependent = locateLiteralsize(argInt, BytesPerOop)); } } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.sista/cogitX64SysV.c b/src/spur64.sista/cogitX64SysV.c index abfac33c85..721537e94e 100644 --- a/src/spur64.sista/cogitX64SysV.c +++ b/src/spur64.sista/cogitX64SysV.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -1043,7 +1043,7 @@ static NoDbgRegParms sqInt genSaveRegs(AbstractInstruction *self_in_CogX64Compil static NoDbgRegParms AbstractInstruction * genSubstituteReturnAddress(AbstractInstruction *self_in_CogX64Compiler, sqInt retpc); static NoDbgRegParms AbstractInstruction * genSwapRRScratch(AbstractInstruction *self_in_CogX64Compiler, sqInt regA, sqInt regB, sqInt regTmp); static NoDbgRegParms sqInt hasVarBaseRegister(AbstractInstruction *self_in_CogX64Compiler); -static NoDbgRegParms sqInt instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); +static NoDbgRegParms int instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); static NoDbgRegParms int is32BitSignedImmediate(AbstractInstruction *self_in_CogX64Compiler, sqInt a64BitUnsignedOperand); static NoDbgRegParms int isCallPrecedingReturnPC(AbstractInstruction *self_in_CogX64Compiler, sqInt mcpc); static NoDbgRegParms sqInt isJumpAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc); @@ -3824,7 +3824,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3851,11 +3851,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5584,7 +5584,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5611,11 +5611,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -6840,7 +6840,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -9920,7 +9920,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9947,11 +9947,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -26686,7 +26686,7 @@ hasVarBaseRegister(AbstractInstruction *self_in_CogX64Compiler) occur within a larger method. This is very far from a full decode. */ /* CogX64Compiler>>#instructionSizeAt: */ -static NoDbgRegParms sqInt +static NoDbgRegParms int instructionSizeAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc) { sqInt op; @@ -26879,7 +26879,7 @@ jumpTargetPCAt(AbstractInstruction *self_in_CogX64Compiler, sqInt pc) { sqInt byte; sqInt offset; - sqInt size; + int size; size = instructionSizeAt(self_in_CogX64Compiler, pc); if (size == 2) { @@ -29423,7 +29423,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -29598,7 +29598,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29625,11 +29625,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29771,8 +29771,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -34539,7 +34539,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -34701,7 +34701,7 @@ genSpecialSelectorComparisonWithoutCounters(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -35416,7 +35416,7 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35443,11 +35443,11 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35806,7 +35806,7 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35833,11 +35833,11 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -38790,7 +38790,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.sista/cogitX64WIN64.c b/src/spur64.sista/cogitX64WIN64.c index a62f058773..192d8e265e 100644 --- a/src/spur64.sista/cogitX64WIN64.c +++ b/src/spur64.sista/cogitX64WIN64.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "SistaCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -3824,7 +3824,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -3851,11 +3851,11 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5584,7 +5584,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -5611,11 +5611,11 @@ collectCogMethodConstituent(CogMethod *cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -6847,7 +6847,7 @@ endPCOf(sqInt aMethod) return pc - 1; } } - bsOffset = /* begin bytecodeSetOffsetFor: */ + bsOffset = /* bytecodeSetOffsetFor: */ (methodUsesAlternateBytecodeSet(aMethod) ? 0x100 : 0); @@ -9935,7 +9935,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -9962,11 +9962,11 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpcSqInt = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpcSqInt = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29473,7 +29473,7 @@ genSpecialSelectorSend(void) sqInt index; sqInt numArgs; - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -29656,7 +29656,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29683,11 +29683,11 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -29829,8 +29829,8 @@ static sqInt numSpecialSelectors(void) { return (bytecodeSetOffset == 0x100 - ? AltNumSpecialSelectors - : NumSpecialSelectors); + ? AltNumSpecialSelectors + : NumSpecialSelectors); } @@ -34597,7 +34597,7 @@ genSpecialSelectorComparison(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -34759,7 +34759,7 @@ genSpecialSelectorComparisonWithoutCounters(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); @@ -35474,7 +35474,7 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35501,11 +35501,11 @@ picDataForBlockEntryMethod(sqInt blockEntryMcpc, sqInt cogMethod) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35864,7 +35864,7 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -35891,11 +35891,11 @@ picDataForinto(CogMethod *cogMethod, sqInt arrayObj) /* skip fiducial; i.e. the map entry for the pc immediately following the method header. */ map -= 1; aMethodObj = (homeMethod->methodObject); - bcpc = startbcpc - (/* begin blockCreationBytecodeSizeForHeader: */ + bcpc = startbcpc - (/* blockCreationBytecodeSizeForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? AltBlockCreationBytecodeSize : BlockCreationBytecodeSize)); - bsOffset = /* begin bytecodeSetOffsetForHeader: */ + bsOffset = /* bytecodeSetOffsetForHeader: */ (headerIndicatesAlternateBytecodeSet((homeMethod->methodHeader)) ? 0x100 : 0); @@ -38848,7 +38848,7 @@ genSpecialSelectorArithmetic(void) /* #MoveCq:R: #gen:quickConstant:operand: #checkQuickConstant:forInstruction: */ genoperandoperand(MoveCqR, argInt, Arg0Reg); } - index = byte0 - (/* begin firstSpecialSelectorBytecodeOffset */ + index = byte0 - (/* firstSpecialSelectorBytecodeOffset */ (bytecodeSetOffset == 0x100 ? AltFirstSpecialSelector + 0x100 : FirstSpecialSelector)); diff --git a/src/spur64.sista/cointerp.c b/src/spur64.sista/cointerp.c index b3d7466c80..4d503fd75c 100644 --- a/src/spur64.sista/cointerp.c +++ b/src/spur64.sista/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1089,6 +1089,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1269,6 +1270,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1304,12 +1306,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1342,6 +1346,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1388,9 +1393,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1822,12 +1827,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1855,7 +1860,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1874,6 +1878,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2688,7 +2693,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -29595,70 +29600,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34255,14 +34246,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34270,32 +34263,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -36399,12 +36434,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -45827,19 +45860,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45899,19 +45925,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -52871,6 +52890,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -57696,19 +57730,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59931,6 +59957,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -61755,6 +61871,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61927,6 +62133,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -63250,6 +63496,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -66126,63 +66411,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -66199,7 +66427,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -66380,6 +66608,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -70438,13 +70723,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -70456,12 +70742,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -72211,8 +72498,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -73731,10 +74018,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -77027,7 +77315,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -78620,6 +78908,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -78666,7 +78955,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.sista/cointerp.h b/src/spur64.sista/cointerp.h index e0499f0680..8d0c43d8b4 100644 --- a/src/spur64.sista/cointerp.h +++ b/src/spur64.sista/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/spur64.sista/gcc3x-cointerp.c b/src/spur64.sista/gcc3x-cointerp.c index 2c07126b2b..d34aa12aae 100644 --- a/src/spur64.sista/gcc3x-cointerp.c +++ b/src/spur64.sista/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1092,6 +1092,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -1272,6 +1273,7 @@ extern void printActivationsOf(sqInt aMethodObj); extern void printBogons(void); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1307,12 +1309,14 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); extern sqInt receiverTagBitsForMethod(sqInt aMethodObj); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1345,6 +1349,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1391,9 +1396,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1825,12 +1830,12 @@ _iss sqInt numStackPages; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt profileProcess; _iss sqInt becomeEffectsFlags; #if LRPCheck _iss sqInt longRunningPrimitiveCheckSemaphore; #endif -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1858,7 +1863,6 @@ _iss sqInt tempOop2; _iss sqInt cogCompiledCodeCompactionCalledFor; _iss usqInt freeOldSpaceStart; _iss sqInt imageHeaderFlags; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lastMethodCacheProbeWrite; @@ -1877,6 +1881,7 @@ _iss usqInt cogCodeSize; _iss usqLong longRunningPrimitiveStartUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2691,7 +2696,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[Spur] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; int displayWidth; int displayDepth; @@ -2847,10 +2852,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -29604,70 +29607,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -34264,14 +34253,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -34279,32 +34270,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -36408,12 +36441,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -45836,19 +45867,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -45908,19 +45932,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -52880,6 +52897,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -57705,19 +57737,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -59940,6 +59964,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -61764,6 +61878,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -61936,6 +62140,46 @@ receiverTagBitsForMethod(sqInt aMethodObj) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -63259,6 +63503,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -66135,63 +66418,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -66208,7 +66434,7 @@ prepareForSnapshot(void) sqInt largeChild; sqInt newEndOfMemory; sqInt next; - sqInt node; + usqInt node; SpurSegmentInfo *seg; sqInt smallChild; sqInt treeNode; @@ -66389,6 +66615,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -70447,13 +70730,14 @@ static sqInt getErrorObjectFromPrimFailCode(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; - sqInt clone; - sqInt errObj; + usqInt clone; + usqInt errObj; sqInt i; usqInt newObj; usqInt numBytes; usqInt numSlots; usqInt numSlotsUsqInt; + sqInt objOop; sqInt table; sqInt valuePointer; @@ -70465,12 +70749,13 @@ getErrorObjectFromPrimFailCode(void) ? ((((usqInt)(((sqInt)((usqInt)((longAt(table - BaseHeaderSize))) << 8)))))) >> 8 : numSlots)))) { /* begin followField:ofObject: */ - errObj = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); + objOop = longAt((table + BaseHeaderSize) + ((((usqInt)((GIV(primFailCode) - 1)) << (shiftForWord()))))); if (/* isOopForwarded: */ - ((!(errObj & (tagMask())))) - && ((!((longAt(errObj)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { - errObj = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, errObj); + ((!(objOop & (tagMask())))) + && ((!((longAt(objOop)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun())))))) { + objOop = fixFollowedFieldofObjectwithInitialValue(GIV(primFailCode) - 1, table, objOop); } + errObj = objOop; /* If there's a clonable object in the table at that index, answer a clone of the error object with the second slot set to the value of secondaryErrorCode. */ @@ -72220,8 +72505,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -73740,10 +74025,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -77036,7 +77322,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -78629,6 +78915,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -78675,7 +78962,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.sista/vmCallback.h b/src/spur64.sista/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur64.sista/vmCallback.h +++ b/src/spur64.sista/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur64.stack.lowcode/gcc3x-interp.c b/src/spur64.stack.lowcode/gcc3x-interp.c index 0a50f4c3bd..a93b07c455 100644 --- a/src/spur64.stack.lowcode/gcc3x-interp.c +++ b/src/spur64.stack.lowcode/gcc3x-interp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -789,6 +789,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -973,6 +974,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1008,11 +1010,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1045,6 +1049,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1091,9 +1096,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1540,8 +1545,8 @@ _iss char * stackPointer; _iss sqInt primFailCode; _iss sqInt argumentCount; _iss usqInt oldSpaceStart; -_iss StackPage * stackPage; _iss sqInt nilObj; +_iss StackPage * stackPage; _iss sqInt bytecodeSetSelector; _iss usqInt method; _iss char * framePointer; @@ -1557,8 +1562,8 @@ _iss sqInt trueObj; _iss sqInt falseObj; _iss usqInt totalFreeOldSpace; _iss SpurSegmentInfo * segments; -_iss sqInt hiddenRootsObj; _iss sqInt needGCFlag; +_iss sqInt hiddenRootsObj; _iss sqInt numSegments; _iss StackPage * pages; _iss char * shadowCallStackPointer; @@ -1569,9 +1574,9 @@ _iss sqInt markStack; _iss sqInt weaklingStack; _iss sqInt numClassTablePages; _iss sqInt bytesPerPage; +_iss usqInt scavengeThreshold; _iss char * stackLimit; _iss sqInt * rememberedSet; -_iss usqInt scavengeThreshold; _iss sqInt remapBufferCount; _iss sqInt classTableFirstPage; _iss usqInt firstFreeObject; @@ -1584,9 +1589,9 @@ _iss char * nativeStackPointer; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1614,7 +1619,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1633,6 +1637,7 @@ _iss usqLong longRunningPrimitiveStartUsecs; _iss usqLong longRunningPrimitiveStopUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -1771,7 +1776,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2409,7 +2414,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; int displayWidth; int displayDepth; @@ -2528,10 +2533,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -25962,70 +25965,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -29944,14 +29933,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -29959,32 +29950,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32182,12 +32215,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -41639,19 +41670,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41711,19 +41735,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -48620,6 +48637,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -53575,19 +53607,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -55824,6 +55848,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -57642,6 +57756,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -57751,6 +57955,46 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -59090,6 +59334,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -61933,63 +62216,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -62187,6 +62413,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -68470,8 +68753,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -70238,10 +70521,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -74238,7 +74522,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -76060,6 +76344,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -76106,7 +76391,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.stack.lowcode/interp.c b/src/spur64.stack.lowcode/interp.c index 0fcae9a1cc..aad425774c 100644 --- a/src/spur64.stack.lowcode/interp.c +++ b/src/spur64.stack.lowcode/interp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -786,6 +786,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -970,6 +971,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -1005,11 +1007,13 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); static NoDbgRegParms sqInt rawClassTagForClass(sqInt classObj); extern sqInt rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1042,6 +1046,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1088,9 +1093,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1537,8 +1542,8 @@ _iss char * stackPointer; _iss sqInt primFailCode; _iss sqInt argumentCount; _iss usqInt oldSpaceStart; -_iss StackPage * stackPage; _iss sqInt nilObj; +_iss StackPage * stackPage; _iss sqInt bytecodeSetSelector; _iss usqInt method; _iss char * framePointer; @@ -1554,8 +1559,8 @@ _iss sqInt trueObj; _iss sqInt falseObj; _iss usqInt totalFreeOldSpace; _iss SpurSegmentInfo * segments; -_iss sqInt hiddenRootsObj; _iss sqInt needGCFlag; +_iss sqInt hiddenRootsObj; _iss sqInt numSegments; _iss StackPage * pages; _iss char * shadowCallStackPointer; @@ -1566,9 +1571,9 @@ _iss sqInt markStack; _iss sqInt weaklingStack; _iss sqInt numClassTablePages; _iss sqInt bytesPerPage; +_iss usqInt scavengeThreshold; _iss char * stackLimit; _iss sqInt * rememberedSet; -_iss usqInt scavengeThreshold; _iss sqInt remapBufferCount; _iss sqInt classTableFirstPage; _iss usqInt firstFreeObject; @@ -1581,9 +1586,9 @@ _iss char * nativeStackPointer; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1611,7 +1616,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1630,6 +1634,7 @@ _iss usqLong longRunningPrimitiveStartUsecs; _iss usqLong longRunningPrimitiveStopUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -1768,7 +1773,7 @@ static signed char primitiveAccessorDepthTable[MaxPrimitiveIndex + 2 /* 584 */] /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*60*/ 0, 0, 0, 0, 0,-1,-1,-1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, /*80*/ -1,-1,-1, 0, 0, 0, 1, 0, 2,-1,-1, 0, 0, 0, 1,-1, 0,-1, 0, 0, -/*100*/ 1, 2, 2, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, +/*100*/ 1, 2, 1, 2,-1, 2,-1,-1,-1,-1, 0, 1, 0, 0,-1, 1, 0, 0, 1, 0, /*120*/ 2, 1,-1,-1, 0, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0,-1, 0,-1,-1, 0, /*140*/ -1, 1,-1, 1, 1, 1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1, 1, 1, /*160*/ 0, 0,-1, 0, 0, 1, 1,-1, 1, 0, 0, 0,-1, 1, 1, 0,-1, 0,-1,-1, @@ -2406,7 +2411,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; int displayWidth; int displayDepth; @@ -25953,70 +25958,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -29935,14 +29926,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -29950,32 +29943,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -32173,12 +32208,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -41630,19 +41663,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -41702,19 +41728,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -48611,6 +48630,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -53566,19 +53600,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -55815,6 +55841,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -57633,6 +57749,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -57742,6 +57948,46 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -59081,6 +59327,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -61924,63 +62209,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -62178,6 +62406,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -68461,8 +68746,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -70229,10 +70514,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -74229,7 +74515,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -76051,6 +76337,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -76097,7 +76384,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.stack.lowcode/vmCallback.h b/src/spur64.stack.lowcode/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur64.stack.lowcode/vmCallback.h +++ b/src/spur64.stack.lowcode/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/spur64.stack/gcc3x-interp.c b/src/spur64.stack/gcc3x-interp.c index 8d7032d876..e53b943465 100644 --- a/src/spur64.stack/gcc3x-interp.c +++ b/src/spur64.stack/gcc3x-interp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -784,6 +784,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -964,6 +965,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -999,10 +1001,12 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1035,6 +1039,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1081,9 +1086,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1523,8 +1528,8 @@ _iss usqInt method; _iss sqInt bytecodeSetSelector; _iss usqInt freeStart; _iss char * framePointer; -_iss sqInt specialObjectsOop; _iss FILE * transcript; +_iss sqInt specialObjectsOop; _iss usqInt endOfMemory; _iss usqInt pastSpaceStart; _iss sqInt messageSelector; @@ -1559,9 +1564,9 @@ _iss usqInt totalHeapSizeIncludingBridges; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1589,7 +1594,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1608,6 +1612,7 @@ _iss usqLong longRunningPrimitiveStartUsecs; _iss usqLong longRunningPrimitiveStopUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2384,7 +2389,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; int displayWidth; int displayDepth; @@ -2501,10 +2506,8 @@ interpret(void) void *theStackMemory; JUMP_TABLE; -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) + if (!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) error("bytecode jumpTable too small"); -#endif if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ @@ -13377,70 +13380,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -17359,14 +17348,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -17374,32 +17365,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -19597,12 +19630,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -29047,19 +29078,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -29119,19 +29143,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -36028,6 +36045,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -40971,19 +41003,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -43184,6 +43208,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -45002,6 +45116,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -45101,6 +45305,46 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -46440,6 +46684,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -49283,63 +49566,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -49537,6 +49763,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -55786,8 +56069,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -57540,10 +57823,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -61479,7 +61763,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -63259,6 +63543,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -63305,7 +63590,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.stack/interp.c b/src/spur64.stack/interp.c index cdc64c5164..d84fda4b4d 100644 --- a/src/spur64.stack/interp.c +++ b/src/spur64.stack/interp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -781,6 +781,7 @@ extern sqInt fetchPointerofObject(sqInt fieldIndex, sqInt objOop); static sqInt findLargestFreeChunk(void); extern void findStringBeginningWith(char *aCString); extern void findString(char *aCString); +static NoDbgRegParms void fireEphemeron(sqInt ephemeron); static sqInt firstAccessibleObject(void); static NoDbgRegParms void * firstFixedFieldOfMaybeImmediate(sqInt oop); extern void * firstFixedField(sqInt objOop); @@ -961,6 +962,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -996,10 +998,12 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); static NoDbgRegParms void queueMourner(sqInt anEphemeronOrWeakArray); extern sqInt rawHashBitsOf(sqInt objOop); +static void refireQueuedEphemeronsPostSnapshot(void); static NoDbgRegParms sqInt relocateObjStackForPlanningCompactorandContents(sqInt objStack, sqInt relocateContents); extern sqInt removeGCRoot(sqInt *varLoc); static NoDbgRegParms sqInt returnrestoringObjectsInsavedFirstFieldsandsavedHashes(sqInt errCode, sqInt firstArray, sqInt savedFirstFields, sqInt secondArray, sqInt savedHashes); @@ -1032,6 +1036,7 @@ static NoDbgRegParms sqInt topOfObjStack(sqInt objStack); extern sqInt topRemappableOop(void); static sqInt totalFreeListBytes(void); extern sqInt trueObject(void); +static void unfireQueuedEphemeronsForSnapshot(void); static NoDbgRegParms sqInt unlinkFreeChunkchunkBytes(sqInt freeChunk, sqInt chunkBytes); static NoDbgRegParms NeverInline sqInt unlinkLilliputianChunkindex(sqInt freeChunk, sqInt index); static NoDbgRegParms void unlinkSolitaryFreeTreeNode(sqInt freeTreeNode); @@ -1078,9 +1083,9 @@ static NoDbgRegParms sqInt isEmptySegment(SpurSegmentInfo *seg); static NoDbgRegParms sqInt isInSegments(usqInt address); static NoDbgRegParms sqInt isValidSegmentBridge(sqInt objOop); static NoDbgRegParms SpurSegmentInfo * nextNonEmptySegmentAfter(sqInt i); -static void postSnapshot(void); static NeverInline void prepareForSnapshot(void); static NoDbgRegParms sqInt readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes); +static void restorePostSnapshot(void); extern SpurSegmentInfo * segmentContainingObj(sqInt objOop); static sqInt segmentOverlap(void); static NoDbgRegParms int shrinkObjectMemory(usqInt delta); @@ -1520,8 +1525,8 @@ _iss usqInt method; _iss sqInt bytecodeSetSelector; _iss usqInt freeStart; _iss char * framePointer; -_iss sqInt specialObjectsOop; _iss FILE * transcript; +_iss sqInt specialObjectsOop; _iss usqInt endOfMemory; _iss usqInt pastSpaceStart; _iss sqInt messageSelector; @@ -1556,9 +1561,9 @@ _iss usqInt totalHeapSizeIncludingBridges; _iss sqInt tempOop; _iss sqInt classTableIndex; _iss usqInt lastMobileObject; +_iss sqInt mournQueue; _iss sqInt numStackPages; _iss sqInt profileProcess; -_iss sqInt mournQueue; _iss sqInt numRememberedEphemerons; _iss sqInt mobileStart; _iss sqInt performWithArgumentsRecursionGuard; @@ -1586,7 +1591,6 @@ _iss sqInt tempOop2; _iss usqInt freeOldSpaceStart; _iss sqInt gcPhaseInProgress; _iss sqInt lastMethodCacheProbeWrite; -_iss sqInt pendingFinalizationSignals; _iss sqInt validatedIntegerClassFlags; _iss usqInt firstMobileObject; _iss sqInt lkupClass; @@ -1605,6 +1609,7 @@ _iss usqLong longRunningPrimitiveStartUsecs; _iss usqLong longRunningPrimitiveStopUsecs; #endif _iss sqInt metaclassNumSlots; +_iss sqInt pendingFinalizationSignals; _iss sqInt shrinkThreshold; _iss usqLong statCheckForEvents; _iss sqInt statTenures; @@ -2381,7 +2386,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; int displayWidth; int displayDepth; @@ -13368,70 +13373,56 @@ primitiveBitXorLargeIntegers(void) EXPORT(sqInt) primitiveBytecodeSetsAvailable(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt encoderNames; + usqInt encoderNames; + usqInt newObj; + usqInt numBytes; char *sp; sqInt valuePointer; if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); - valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } + /* begin eeInstantiateSmallClassIndex:format:numSlots: */ + assert((knownClassAtIndex(ClassArrayCompactIndex)) != GIV(nilObj)); + assert((arrayFormat()) == (instSpecOfClass(knownClassAtIndex(ClassArrayCompactIndex)))); + + /* begin allocateSmallNewSpaceSlots:format:classIndex: */ + newObj = GIV(freeStart); + numBytes = BaseHeaderSize + (3 * BytesPerOop); + assert((numBytes % (allocationUnit())) == 0); + assert((newObj % (allocationUnit())) == 0); + if ((GIV(freeStart) + numBytes) > GIV(scavengeThreshold)) { + if (!GIV(needGCFlag)) { + /* begin scheduleScavenge */ + GIV(needGCFlag) = 1; + forceInterruptCheck(); + } + if ((GIV(freeStart) + numBytes) > (((GIV(eden)).limit))) { + error("no room in eden for allocateSmallNewSpaceSlots:format:classIndex:"); + encoderNames = 0; + goto l1; } } + long64Atput(newObj, ((((((usqLong) 3)) << (numSlotsFullShift()))) + ((((usqInt)((arrayFormat())) << (formatShift()))))) + ClassArrayCompactIndex); + GIV(freeStart) += numBytes; + encoderNames = newObj; + /* end eeInstantiateSmallClassIndex:format:numSlots: */ +l1: + valuePointer = stringForCString("EncoderForV3"); - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForSistaV1"); - /* begin storePointer:ofObject:withValue: */ - assert(!(isForwarded(encoderNames))); - if ((/* begin isOldObject: */ - assert(isNonImmediate(encoderNames)), - oopisGreaterThanOrEqualTo(encoderNames, GIV(oldSpaceStart)))) { - if (/* isYoung: */ - ((!(valuePointer & (tagMask())))) - && (oopisLessThan(valuePointer, GIV(oldSpaceStart)))) { - /* begin possibleRootStoreInto: */ - if (!((((usqInt)((longAt(encoderNames)))) >> (rememberedBitShift())) & 1)) { - remember(encoderNames); - } - } - } - - /* most stores into young objects */ + /* begin storePointerUnchecked:ofObject:withValue: */ + assert(!(isOopForwarded(encoderNames))); longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ @@ -17350,14 +17341,16 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; + sqInt fmt; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + usqInt numBytes; + usqInt numSlots; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -17365,32 +17358,74 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((!(obj & (tagMask())))) + && (((((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask())) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); - } + + /* begin byteSizeOf: */ + if (((obj & (tagMask())) != 0)) { + sz = 0; + goto l1; } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; + /* begin numBytesOf: */ + fmt = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + assert((classIndexOf(obj)) > (isForwardedObjectClassIndexPun())); + numBytes = (((numSlots = byteAt(obj + 7))) == (numSlotsMask()) + ? ((((usqInt)(((sqInt)((usqInt)((longAt(obj - BaseHeaderSize))) << 8)))))) >> 8 + : numSlots); + numBytes = (numBytes << (shiftForWord())); + if (fmt >= (firstByteFormat())) { + sz = numBytes - (fmt & 7); + goto l1; + } + + /* bytes (the common case), including CompiledMethod */ + if (fmt <= (sixtyFourBitIndexableFormat())) { + sz = numBytes; + goto l1; + } + if (fmt >= (firstShortFormat())) { + sz = numBytes - (((fmt & 3) << 1)); + goto l1; + } + + /* fmt >= self firstLongFormat */ + sz = numBytes - (((fmt & 1) << 2)); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; + } + } return 0; } @@ -19588,12 +19623,10 @@ primitiveMultipleBytecodeSetsActive(void) GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -29038,19 +29071,12 @@ processEphemerons(void) && (isObjEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -29110,19 +29136,12 @@ processEphemerons(void) && (isMaybeFiredEphemeron(ephemeron))); key = longAt((ephemeron + BaseHeaderSize) + (0U << (shiftForWord()))); if (!(isScavengeSurvivor(key))) { - /* begin fireEphemeron: */ - queueMourner(ephemeron); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; valuePointer = copyAndForward(key); /* begin storePointerUnchecked:ofObject:withValue: */ assert(!(isOopForwarded(ephemeron))); longAtput((ephemeron + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); + fireEphemeron(ephemeron); } /* Fired ephemerons should have had their format changed. */ @@ -36019,6 +36038,21 @@ findString(char *aCString) } } + /* SpurMemoryManager>>#fireEphemeron: */ +static NoDbgRegParms void +fireEphemeron(sqInt ephemeron) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + queueMourner(ephemeron); + + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(ephemeron, ((longAt(ephemeron)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + + /* begin signalFinalization: */ + forceInterruptCheck(); + GIV(pendingFinalizationSignals) += 1; +} + /* SpurMemoryManager>>#firstAccessibleObject */ static sqInt firstAccessibleObject(void) @@ -40962,19 +40996,11 @@ markWeaklingsAndMarkAndFireEphemerons(void) assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); for (p = ((GIV(unscannedEphemerons).start)); p <= (((GIV(unscannedEphemerons).top)) - BytesPerOop); p += BytesPerOop) { - /* begin fireEphemeron: */ - queueMourner(longAt(p)); - assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); - longAtput(longAt(p), ((longAt(longAt(p))) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); - - /* begin signalFinalization: */ - forceInterruptCheck(); - GIV(pendingFinalizationSignals) += 1; + fireEphemeron(longAt(p)); } } /* begin markAllUnscannedEphemerons */ - assert(!(noUnscannedEphemerons())); assert(allUnscannedEphemeronsAreActive()); while (((GIV(unscannedEphemerons).top)) > ((GIV(unscannedEphemerons).start))) { ephemeron = longAt((GIV(unscannedEphemerons).start)); @@ -43175,6 +43201,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == 5 /* ephemeronFormat */) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -44993,6 +45109,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + usqInt numSlots; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + address = /* startAddressForBridgedHeapEnumeration */ + (GIV(pastSpaceStart) > (((GIV(pastSpace)).start)) + ? ((GIV(pastSpace)).start) + : (GIV(freeStart) > (((GIV(eden)).start)) + ? ((GIV(eden)).start) + : GIV(oldSpaceStart))); + + /* begin objectStartingAt: */ + numSlots = byteAt(address + 7); + startObject = (numSlots == (numSlotsMask()) + ? address + BaseHeaderSize + : address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = (longAt(obj)) & (classIndexMask()); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = (((usqInt)((longAt(obj)))) >> (formatShift())) & (formatMask()); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -45092,6 +45298,46 @@ rawHashBitsOf(sqInt objOop) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. + This must be undone post snapshot. */ + + /* SpurMemoryManager>>#refireQueuedEphemeronsPostSnapshot */ +static void +refireQueuedEphemeronsPostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 5 /* ephemeronFormat */)) { + /* begin setFormatOf:to: */ + assert(((1 /* nonIndexablePointerFormat */ >= 0) && (1 /* nonIndexablePointerFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (1U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Relocate all objStack pages that comprise objStack, including contents if requested. */ @@ -46431,6 +46677,45 @@ trueObject(void) } +/* Ephemerons in the mourn queue will have been fired (had their + ephemeron-ness turned off), + but the ephemeron queue is not saved in the snapshot. So the snapshotted + ephemerons need to be unfired so they're still unqueued ephemerons in the + loaded image. */ + + /* SpurMemoryManager>>#unfireQueuedEphemeronsForSnapshot */ +static void +unfireQueuedEphemeronsForSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt iSqInt; + sqInt mourner; + sqInt numOnThisPage; + sqInt objStackPage; + + /* begin objStack:do: */ + if (GIV(mournQueue) == GIV(nilObj)) { + goto l1; + } + eassert(isValidObjStack(GIV(mournQueue))); + objStackPage = GIV(mournQueue); + while (objStackPage != 0) { + numOnThisPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackTopx) << (shiftForWord()))))); + for (iSqInt = ((numOnThisPage + ObjStackFixedSlots) - 1); iSqInt >= ObjStackFixedSlots; iSqInt += -1) { + mourner = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(iSqInt) << (shiftForWord()))))); + if (((!(mourner & (tagMask())))) + && (((((usqInt)((longAt(mourner)))) >> (formatShift())) & (formatMask())) == 1 /* nonIndexablePointerFormat */)) { + /* begin setFormatOf:to: */ + assert(((5 /* ephemeronFormat */ >= 0) && (5 /* ephemeronFormat */ <= (formatMask())))); + longAtput(mourner, ((longAt(mourner)) & (~(usqIntptr_t)(((sqInt)((usqInt)((formatMask())) << (formatShift())))))) + (5U << (formatShift()))); + } + } + objStackPage = longAt((objStackPage + BaseHeaderSize) + ((((usqInt)(ObjStackNextx) << (shiftForWord()))))); + } + /* end objStack:do: */ +l1:; +} + + /* Unlink a free object from the free lists. Do not alter totalFreeOldSpace. Used for coalescing. */ @@ -49274,63 +49559,6 @@ nextNonEmptySegmentAfter(sqInt i) } -/* Restore all shortened segments to their proper size, re-freeing the - trailing space. - */ - - /* SpurSegmentManager>>#postSnapshot */ -static void -postSnapshot(void) -{ DECL_MAYBE_SQ_GLOBAL_STRUCT - sqInt address; - sqInt bytes; - usqInt freeChunk; - sqInt i; - sqInt newEndOfMemory; - SpurSegmentInfo *seg; - - - /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ - seg = (&(GIV(segments)[GIV(numSegments) - 1])); - if ((seg->lastFreeObject)) { - newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - - /* begin setEndOfMemory: */ - GIV(endOfMemory) = newEndOfMemory; - if (GIV(freeOldSpaceStart) > newEndOfMemory) { - GIV(freeOldSpaceStart) = newEndOfMemory; - } - } - else { - assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); - } - for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { - seg = (&(GIV(segments)[i])); - freeChunk = (seg->lastFreeObject); - if (freeChunk) { - address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); - (seg->segSize = (seg->savedSegSize)); - bridgeFromto(seg, (i < (GIV(numSegments) - 1) - ? (&(GIV(segments)[i + 1])) - : 0)); - bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); - - /* begin addFreeChunkWithBytes:at: */ - GIV(totalFreeOldSpace) += bytes; - freeChunkWithBytesat(bytes, address); - } - } - checkSegments(); - - /* begin checkFreeSpace: */ - assert(bitsSetInFreeSpaceMaskForAllFreeLists()); - assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); - if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { - runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); - } -} - - /* shorten all segments by any trailing free space. */ /* SpurSegmentManager>>#prepareForSnapshot */ @@ -49528,6 +49756,63 @@ readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes) } +/* Restore all shortened segments to their proper size, re-freeing the + trailing space. + */ + + /* SpurSegmentManager>>#restorePostSnapshot */ +static void +restorePostSnapshot(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + sqInt address; + sqInt bytes; + usqInt freeChunk; + sqInt i; + sqInt newEndOfMemory; + SpurSegmentInfo *seg; + + + /* Set endOfMemory first, to avoid assert fails in freeChunkWithBytes:at:. */ + seg = (&(GIV(segments)[GIV(numSegments) - 1])); + if ((seg->lastFreeObject)) { + newEndOfMemory = (((seg->savedSegSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + + /* begin setEndOfMemory: */ + GIV(endOfMemory) = newEndOfMemory; + if (GIV(freeOldSpaceStart) > newEndOfMemory) { + GIV(freeOldSpaceStart) = newEndOfMemory; + } + } + else { + assert((GIV(endOfMemory)) == ((segLimit(seg)) - (bridgeSize()))); + } + for (i = (GIV(numSegments) - 1); i >= 0; i += -1) { + seg = (&(GIV(segments)[i])); + freeChunk = (seg->lastFreeObject); + if (freeChunk) { + address = (((seg->segSize)) + ((seg->segStart))) - (2 * BaseHeaderSize); + (seg->segSize = (seg->savedSegSize)); + bridgeFromto(seg, (i < (GIV(numSegments) - 1) + ? (&(GIV(segments)[i + 1])) + : 0)); + bytes = ((((seg->segSize)) + ((seg->segStart))) - address) - (2 * BaseHeaderSize); + + /* begin addFreeChunkWithBytes:at: */ + GIV(totalFreeOldSpace) += bytes; + freeChunkWithBytesat(bytes, address); + } + } + checkSegments(); + + /* begin checkFreeSpace: */ + assert(bitsSetInFreeSpaceMaskForAllFreeLists()); + assert(GIV(totalFreeOldSpace) == (totalFreeListBytes())); + if (((checkForLeaks & (GCCheckFreeSpace | GCModeFull)) == (GCCheckFreeSpace | GCModeFull))) { + runLeakCheckerForFreeSpaceignoring(GCCheckFreeSpace, null); + } +} + + /* Answer the segment containing an object. This is mostly for assert checking, but variations on the incremental GC may use it in anger. Binary search is (of @@ -55777,8 +56062,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } @@ -57531,10 +57816,11 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) ? ((firstBytecode = (aMethodObj + ((LiteralStart + (((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) * BytesPerOop)) + BaseHeaderSize), (byteAt(firstBytecode + 1)) + ((((usqInt)((byteAt(firstBytecode + 2))) << 8)))) : 0)) > 0) - && ((/* begin longStoreBytecodeForHeader: */ + && ((/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode - : LongStoreBytecode)) == (fetchByteofObject(((((assert((((methodHeader) & 7) == 1)), + : LongStoreBytecode)) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask)) + LiteralStart) * BytesPerOop) + 3 /* sizeOfCallPrimitiveBytecode: */, aMethodObj))); } @@ -61470,7 +61756,7 @@ reapAndResetErrorCodeToheader(char *theSP, sqInt methodHeader) assert((((methodHeader) & 7) == 1)), /* literalCountOfAlternateHeader: */ ((methodHeader >> 3)) & AlternateHeaderNumLiteralsMask))) * BytesPerOop)) + BaseHeaderSize) + 3 /* sizeOfCallPrimitiveBytecode: */; - if ((byteAt(initialPC)) == (/* begin longStoreBytecodeForHeader: */ + if ((byteAt(initialPC)) == (/* longStoreBytecodeForHeader: */ ((((sqLong) methodHeader)) < 0 ? AltLongStoreBytecode : LongStoreBytecode))) { @@ -63250,6 +63536,7 @@ snapshot(sqInt embedded) /* begin biasForGC */ GIV(biasForGC) = 1; + unfireQueuedEphemeronsForSnapshot(); prepareForSnapshot(); /* begin checkFreeSpace: */ @@ -63296,7 +63583,10 @@ snapshot(sqInt embedded) rcvr := self popStack. ''pop rcvr'' self push: trueObj. to arrange that the snapshot resumes with true. N.B. stackIndex is one-relative. */ - postSnapshot(); + + /* begin postSnapshot */ + restorePostSnapshot(); + refireQueuedEphemeronsPostSnapshot(); marryContextInNewStackPageAndInitializeInterpreterRegisters(activeContext); if (GIV(primFailCode)) { /* begin push: */ diff --git a/src/spur64.stack/validImage.c b/src/spur64.stack/validImage.c index 8ffd5c415b..13e4de3979 100644 --- a/src/spur64.stack/validImage.c +++ b/src/spur64.stack/validImage.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - ImageLeakChecker VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + ImageLeakChecker VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "ImageLeakChecker VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "ImageLeakChecker VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -240,6 +240,7 @@ typedef struct _StackPage { # define NeverInline /*empty*/ #endif +extern NeverInline void eekcr(void); static NoDbgRegParms sqInt growOldSpaceByAtLeast(sqInt minAmmount); static NoDbgRegParms void initializeInterpreter(sqInt bytesToShift); extern void * ioLoadFunctionFrom(char *functionName, char *moduleName); @@ -564,6 +565,7 @@ static NoDbgRegParms void printBridgeon(sqInt oop, FILE *aStream); static NoDbgRegParms void printCantBeObjecton(sqInt oop, FILE *aStream); extern void printContextReferencesTo(sqInt anOop); extern void printEntity(sqInt oop); +extern void printEphemerons(void); extern void printForwarders(void); static NoDbgRegParms void printForwarderon(sqInt oop, FILE *aStream); extern void printFreeChunks(void); @@ -599,6 +601,7 @@ static NoDbgRegParms void printStringDataOfon(sqInt oop, FILE *aStream); #if LLDB extern void printUnmarkedOops(void); #endif /* LLDB */ +extern void printWeaklings(void); static NoDbgRegParms sqInt pushOnUnscannedEphemeronsStack(sqInt anEphemeron); extern void pushRemappableOop(sqInt oop); extern sqInt rawHashBitsOf(sqInt objOop); @@ -675,7 +678,6 @@ static void checkAssumedCompactClasses(void); extern sqInt checkImageHeaderFromBytesAndSize(char *bytes, sqInt totalSize); static NoDbgRegParms sqInt checkImageVersionFromstartingAtassignRawVersion(sqImageFile f, squeakFileOffsetType imageOffset, sqInt *rawVersionPtr); static sqInt convertFloatsToPlatformOrder(void); -extern NeverInline void eekcr(void); static sqInt elementsPerPrintOopLine(void); static NoDbgRegParms void ensureImageFormatIsUpToDate(sqInt swapBytes); static NoDbgRegParms sqInt fetchStackPointerOf(sqInt aContext); @@ -761,8 +763,8 @@ _iss FILE * transcript; _iss sqInt specialObjectsOop; _iss sqInt * freeLists; _iss usqInt freeListsMask; -_iss sqInt markStack; _iss sqInt numClassTablePages; +_iss sqInt markStack; _iss sqInt hiddenRootsObj; _iss sqInt numSegments; _iss SpurSegmentInfo * segments; @@ -782,8 +784,8 @@ _iss sqInt thisClassIndex; _iss sqInt metaclassNumSlots; _iss usqInt newSpaceStart; _iss sqInt numSegInfos; -_iss sqInt mournQueue; _iss sqInt verbose; +_iss sqInt mournQueue; _iss sqInt classTableFirstPage; _iss sqInt falseObj; _iss sqInt rememberedSetLimit; @@ -1005,7 +1007,7 @@ sqInt extraVMMemory; sqInt ffiExceptionResponse; sqInt inIOProcessEvents; struct VirtualMachine* interpreterProxy; -const char *interpreterVersion = "Open Smalltalk ImageChecker VM [ImageLeakChecker VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk ImageChecker VM [ImageLeakChecker VMMaker.oscog-eem.3482]"; usqInt maxOldSpaceSize; sqInt suppressHeartbeatFlag; int displayDepth; @@ -1082,6 +1084,18 @@ int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); /*** Methods ***/ + +/* For marking the end of a leak check print message */ + + /* ImageLeakChecker>>#eekcr */ +NeverInline void +eekcr(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + if (GIV(verbose)) { + printf("\n"); + } +} + /* ImageLeakChecker>>#growOldSpaceByAtLeast: */ static NoDbgRegParms sqInt growOldSpaceByAtLeast(sqInt minAmmount) @@ -9196,6 +9210,96 @@ printEntity(sqInt oop) } +/* Actually print all objects that have ephemeron format. */ + + /* SpurMemoryManager>>#printEphemerons */ +void +printEphemerons(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + usqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + /* begin startAddressForBridgedHeapEnumeration */ + if (GIV(pastSpaceStart) > (((GIV(pastSpace)).start))) { + address = ((GIV(pastSpace)).start); + } + else { + if (GIV(freeStart) > (((GIV(eden)).start))) { + address = ((GIV(eden)).start); + } + else { + address = GIV(oldSpaceStart); + } + } + startObject = objectStartingAt(address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = classIndexOf(obj); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = formatOf(obj); + if (format == (ephemeronFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* useful for VM debugging */ /* SpurMemoryManager>>#printForwarders */ @@ -10926,6 +11030,96 @@ printUnmarkedOops(void) #endif /* LLDB */ +/* Print all objects that have weak array format. */ + + /* SpurMemoryManager>>#printWeaklings */ +void +printWeaklings(void) +{ DECL_MAYBE_SQ_GLOBAL_STRUCT + usqInt address; + sqInt classIndex; + sqInt followingWord; + usqInt followingWordAddress; + sqInt format; + sqInt nSoFar; + sqInt obj; + sqInt prevObj; + sqInt prevPrevObj; + sqInt startObject; + + nSoFar = 0; + + /* begin allObjectsDo: */ + /* begin startAddressForBridgedHeapEnumeration */ + if (GIV(pastSpaceStart) > (((GIV(pastSpace)).start))) { + address = ((GIV(pastSpace)).start); + } + else { + if (GIV(freeStart) > (((GIV(eden)).start))) { + address = ((GIV(eden)).start); + } + else { + address = GIV(oldSpaceStart); + } + } + startObject = objectStartingAt(address); + + /* begin allEntitiesFrom:do: */ + prevPrevObj = (prevObj = null); + obj = startObject; + enableObjectEnumerationFrom(startObject); + while (1) { + assert((obj % (allocationUnit())) == 0); + if (!(oopisLessThan(obj, GIV(endOfMemory)))) break; + assert((long64At(obj)) != 0); + + /* begin isEnumerableObject: */ + classIndex = classIndexOf(obj); + assert((classIndex == (segmentBridgePun())) + || ((classIndex == (isForwardedObjectClassIndexPun())) + || (((long64At(obj)) != 0) + && (classIndex < (GIV(numClassTablePages) * (classTablePageSize())))))); + if (classIndex >= (isForwardedObjectClassIndexPun())) { + format = formatOf(obj); + if (format == (weakArrayFormat())) { + printf("0x%" PRIxSQINT "", obj); + if (((nSoFar += 1)) >= 4) { + nSoFar = 0; + cr(); + } + else { + /* begin space */ + printChar(' '); + } + } + } + prevPrevObj = prevObj; + prevObj = obj; + + /* begin objectAfterMaybeSlimBridge:limit: */ + followingWordAddress = addressAfter(obj); + if (oopisGreaterThanOrEqualTo(followingWordAddress, GIV(endOfMemory))) { + obj = GIV(endOfMemory); + goto l1; + } + flag("endianness"); + followingWord = longAt(followingWordAddress); + obj = ((((usqInt)(followingWord)) >> (numSlotsFullShift())) == (numSlotsMask()) + ? ((oopisLessThan(obj, GIV(oldSpaceStart))) + && ((followingWord & 0xFFFFFFFFFFFFFFLL) == 1) + ? (followingWordAddress + BaseHeaderSize) + BaseHeaderSize + : followingWordAddress + BaseHeaderSize) + : followingWordAddress); + /* end objectAfterMaybeSlimBridge:limit: */ +l1: + assert(oopisGreaterThan(obj, prevObj)); + } + if (nSoFar > 0) { + cr(); + } +} + + /* Attempt to push anEphemeron on the unscanned ephemerons stack and answer if the attempt succeeded. Note that the ephemeron stack overflowing isn't a disaster; it simply means treating the @@ -12737,16 +12931,6 @@ convertFloatsToPlatformOrder(void) return 0; } - -/* For marking the end of a leak check print message */ - - /* StackInterpreter>>#eekcr */ -NeverInline void -eekcr(void) -{ - printf("\n"); -} - /* StackInterpreter>>#elementsPerPrintOopLine */ static sqInt elementsPerPrintOopLine(void) @@ -13438,8 +13622,8 @@ sqInt longStoreBytecodeForHeader(sqInt methodHeader) { return ((((sqLong) methodHeader)) < 0 - ? AltLongStoreBytecode - : LongStoreBytecode); + ? AltLongStoreBytecode + : LongStoreBytecode); } diff --git a/src/spur64.stack/vmCallback.h b/src/spur64.stack/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/spur64.stack/vmCallback.h +++ b/src/spur64.stack/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/v3.cog/cogit.h b/src/v3.cog/cogit.h index 0ccf9acd3f..bc49a744bf 100644 --- a/src/v3.cog/cogit.h +++ b/src/v3.cog/cogit.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/v3.cog/cogitARMv5.c b/src/v3.cog/cogitARMv5.c index 6d91051395..b928e7763b 100644 --- a/src/v3.cog/cogitARMv5.c +++ b/src/v3.cog/cogitARMv5.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7697,7 +7697,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -7722,7 +7722,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -9307,7 +9307,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -9332,7 +9332,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -13385,7 +13385,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -13410,7 +13410,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co map -= 1; aMethodObj = (homeMethod->methodObject); bcpcSqInt = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpcSqInt, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpcSqInt + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -21948,7 +21948,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -21973,7 +21973,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) diff --git a/src/v3.cog/cogitIA32.c b/src/v3.cog/cogitIA32.c index 8c52cdd229..ef352ed936 100644 --- a/src/v3.cog/cogitIA32.c +++ b/src/v3.cog/cogitIA32.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGenerator VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + CCodeGenerator VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f + StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3470 uuid: 5eca4261-1c46-4eb4-bd5f-803847c2ab7f " __DATE__ ; +static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__cogitBuildInfo = __buildInfo; @@ -7510,7 +7510,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -7535,7 +7535,7 @@ bytecodePCForstartBcpcin(sqInt mcpc, sqInt startbcpc, CogBlockMethod *cogMethod) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -9095,7 +9095,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -9120,7 +9120,7 @@ collectCogMethodConstituent(CogMethod *cogMethod) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -12924,7 +12924,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -12949,7 +12949,7 @@ mcPCForBackwardBranchstartBcpcin(sqInt bcpc, sqInt startbcpc, CogBlockMethod *co map -= 1; aMethodObj = (homeMethod->methodObject); bcpcSqInt = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpcSqInt, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpcSqInt + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) @@ -20114,7 +20114,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) latestContinuation = startbcpc; aMethodObj = (homeMethod->methodObject); endbcpc = (numBytesOf(aMethodObj)) - 1; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; /* If the method has a primitive, skip it and the error code store, if any; Logically. these come before the stack check and so must be ignored. */ @@ -20139,7 +20139,7 @@ mapPCDataForinto(CogMethod *cogMethod, sqInt arrayObj) map -= 1; aMethodObj = (homeMethod->methodObject); bcpc = startbcpc - BlockCreationBytecodeSize; - bsOffset = 0 /* begin bytecodeSetOffsetForHeader: */; + bsOffset = 0 /* bytecodeSetOffsetForHeader: */; byte = (fetchByteofObject(bcpc, aMethodObj)) + bsOffset; descriptor = generatorAt(byte); endbcpc = (bcpc + ((descriptor->numBytes))) + (((descriptor->isBlockCreation) diff --git a/src/v3.cog/cointerp.c b/src/v3.cog/cointerp.c index 77cd17102d..1c10968f56 100644 --- a/src/v3.cog/cointerp.c +++ b/src/v3.cog/cointerp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1456,8 +1456,8 @@ _iss FILE * transcript; _iss usqInt method; _iss StackPage * pages; _iss char * stackBasePlus1; -_iss usqInt youngStart; _iss sqInt messageSelector; +_iss usqInt youngStart; _iss sqInt trueObj; _iss sqInt falseObj; _iss sqInt bytesPerPage; @@ -1509,6 +1509,7 @@ _iss sqInt statShrinkMemory; _iss sqInt statTenures; _iss sqInt edenBytes; _iss usqInt fwdTableLast; +_iss sqInt multipleBytecodeSetsActive; _iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt statCompMoveCount; @@ -1518,7 +1519,6 @@ _iss sqInt statMkFwdCount; _iss sqInt tenuringThreshold; _iss sqInt forceTenureFlag; _iss sqInt fullScreenFlag; -_iss sqInt multipleBytecodeSetsActive; _iss sqInt signalLowSpace; _iss sqInt statNumMaps; _iss sqInt statRootTableOverflows; @@ -2254,7 +2254,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[SqueakV3] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[SqueakV3] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -21885,28 +21885,15 @@ primitiveBytecodeSetsAvailable(void) if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); + encoderNames = eeInstantiateSmallClassIndexformatnumSlots(ClassArrayCompactIndex, arrayFormat(), 2); valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); - valuePointer = stringForCString("EncoderForSistaV1"); - - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } - longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ assert(!((failed()))); @@ -25171,14 +25158,13 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -25186,32 +25172,50 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((obj & 1) == 0) + && (((((usqInt)((longAt(obj)))) >> (instFormatFieldLSB())) & 15) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; + } + + /* begin byteSizeOf: */ + if ((obj & 1)) { + sz = 0; + goto l1; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); + sz = numBytesOf(obj); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; } } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; return 0; } @@ -26912,14 +26916,13 @@ primitiveMultipleBytecodeSetsActive(void) if (GIV(argumentCount) == 1) { if ((longAt(GIV(stackPointer))) == GIV(trueObj)) { return (GIV(primFailCode) = PrimErrUnsupported); + GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -47431,7 +47434,7 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) assert((((((CogMethod *) header))->objectHeader)) == (nullHeaderForMachineCodeMethod())), ((((CogMethod *) header))->methodHeader))); return ((primitiveIndexOfMethodheader(aMethodObj, methodHeader)) > 0) - && ((LongStoreBytecode) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + && (LongStoreBytecode == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ assert((methodHeader & 1)), ((((int) methodHeader)) < 0 ? ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask @@ -52857,7 +52860,7 @@ wakeHighestPriority(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt ctxt; sqInt oop; - int p; + sqInt p; sqInt proc; sqInt processList; sqInt schedLists; diff --git a/src/v3.cog/cointerp.h b/src/v3.cog/cointerp.h index 01fb553264..1d10e80840 100644 --- a/src/v3.cog/cointerp.h +++ b/src/v3.cog/cointerp.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ diff --git a/src/v3.cog/gcc3x-cointerp.c b/src/v3.cog/gcc3x-cointerp.c index 0a792d8506..e81862de67 100644 --- a/src/v3.cog/gcc3x-cointerp.c +++ b/src/v3.cog/gcc3x-cointerp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1459,8 +1459,8 @@ _iss FILE * transcript; _iss usqInt method; _iss StackPage * pages; _iss char * stackBasePlus1; -_iss usqInt youngStart; _iss sqInt messageSelector; +_iss usqInt youngStart; _iss sqInt trueObj; _iss sqInt falseObj; _iss sqInt bytesPerPage; @@ -1512,6 +1512,7 @@ _iss sqInt statShrinkMemory; _iss sqInt statTenures; _iss sqInt edenBytes; _iss usqInt fwdTableLast; +_iss sqInt multipleBytecodeSetsActive; _iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt statCompMoveCount; @@ -1521,7 +1522,6 @@ _iss sqInt statMkFwdCount; _iss sqInt tenuringThreshold; _iss sqInt forceTenureFlag; _iss sqInt fullScreenFlag; -_iss sqInt multipleBytecodeSetsActive; _iss sqInt signalLowSpace; _iss sqInt statNumMaps; _iss sqInt statRootTableOverflows; @@ -2257,7 +2257,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Cog[SqueakV3] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Cog[SqueakV3] VM [CoInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2371,12 +2371,6 @@ interpret(void) sqInt stackZoneBytes; void *theStackMemory; JUMP_TABLE; - -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) - error("bytecode jumpTable too small"); -#endif - if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ /* begin ensureInitializeStackZone */ @@ -21894,28 +21888,15 @@ primitiveBytecodeSetsAvailable(void) if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); + encoderNames = eeInstantiateSmallClassIndexformatnumSlots(ClassArrayCompactIndex, arrayFormat(), 2); valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); - valuePointer = stringForCString("EncoderForSistaV1"); - - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } - longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ assert(!((failed()))); @@ -25180,14 +25161,13 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -25195,32 +25175,50 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((obj & 1) == 0) + && (((((usqInt)((longAt(obj)))) >> (instFormatFieldLSB())) & 15) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); + + /* begin byteSizeOf: */ + if ((obj & 1)) { + sz = 0; + goto l1; + } + sz = numBytesOf(obj); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; } } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; return 0; } @@ -26921,14 +26919,13 @@ primitiveMultipleBytecodeSetsActive(void) if (GIV(argumentCount) == 1) { if ((longAt(GIV(stackPointer))) == GIV(trueObj)) { return (GIV(primFailCode) = PrimErrUnsupported); + GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -47440,7 +47437,7 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) assert((((((CogMethod *) header))->objectHeader)) == (nullHeaderForMachineCodeMethod())), ((((CogMethod *) header))->methodHeader))); return ((primitiveIndexOfMethodheader(aMethodObj, methodHeader)) > 0) - && ((LongStoreBytecode) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + && (LongStoreBytecode == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ assert((methodHeader & 1)), ((((int) methodHeader)) < 0 ? ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask @@ -52866,7 +52863,7 @@ wakeHighestPriority(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt ctxt; sqInt oop; - int p; + sqInt p; sqInt proc; sqInt processList; sqInt schedLists; diff --git a/src/v3.cog/vmCallback.h b/src/v3.cog/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/v3.cog/vmCallback.h +++ b/src/v3.cog/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8 diff --git a/src/v3.stack/gcc3x-interp.c b/src/v3.stack/gcc3x-interp.c index 8b47e74c0c..b0b7a094eb 100644 --- a/src/v3.stack/gcc3x-interp.c +++ b/src/v3.stack/gcc3x-interp.c @@ -2,12 +2,12 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1253,6 +1253,7 @@ _iss sqInt statShrinkMemory; _iss sqInt statTenures; _iss sqInt edenBytes; _iss usqInt fwdTableLast; +_iss sqInt multipleBytecodeSetsActive; _iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt printSends; @@ -1264,7 +1265,6 @@ _iss sqInt tenuringThreshold; _iss sqInt externalPrimitiveTableFirstFreeIndex; _iss sqInt forceTenureFlag; _iss sqInt fullScreenFlag; -_iss sqInt multipleBytecodeSetsActive; _iss sqInt signalLowSpace; _iss sqInt statNumMaps; _iss sqInt statRootTableOverflows; @@ -1985,7 +1985,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -2061,12 +2061,6 @@ interpret(void) sqInt stackZoneBytes; void *theStackMemory; JUMP_TABLE; - -#if MULTIPLEBYTECODESETS - if(!asserta((sizeof(jumpTable)/sizeof(jumpTable[0])) >= 512)) - error("bytecode jumpTable too small"); -#endif - if (!GIV(stackLimit)) { /* begin initStackPagesAndInterpret */ /* begin ensureInitializeStackZone */ @@ -10238,28 +10232,15 @@ primitiveBytecodeSetsAvailable(void) if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); + encoderNames = eeInstantiateSmallClassIndexformatnumSlots(ClassArrayCompactIndex, arrayFormat(), 2); valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); - valuePointer = stringForCString("EncoderForSistaV1"); - - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } - longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ assert(!((failed()))); @@ -13192,14 +13173,13 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -13207,32 +13187,50 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((obj & 1) == 0) + && (((((usqInt)((longAt(obj)))) >> (instFormatFieldLSB())) & 15) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); + + /* begin byteSizeOf: */ + if ((obj & 1)) { + sz = 0; + goto l1; + } + sz = numBytesOf(obj); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; } } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; return 0; } @@ -15026,14 +15024,13 @@ primitiveMultipleBytecodeSetsActive(void) if (GIV(argumentCount) == 1) { if ((longAt(GIV(stackPointer))) == GIV(trueObj)) { return (GIV(primFailCode) = PrimErrUnsupported); + GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -35862,7 +35859,7 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) assert(isCompiledMethod(aMethodObj)); methodHeader = longAt((aMethodObj + BaseHeaderSize) + ((((usqInt)(HeaderIndex) << (shiftForWord()))))); return ((primitiveIndexOfMethodheader(aMethodObj, methodHeader)) > 0) - && ((LongStoreBytecode) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + && (LongStoreBytecode == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ assert((methodHeader & 1)), ((((int) methodHeader)) < 0 ? ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask diff --git a/src/v3.stack/interp.c b/src/v3.stack/interp.c index 48a9fcfed5..c757ac6544 100644 --- a/src/v3.stack/interp.c +++ b/src/v3.stack/interp.c @@ -1,10 +1,10 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) from - StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 */ -static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 " __DATE__ ; +static char __buildInfo[] = "StackInterpreter VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 " __DATE__ ; char *__interpBuildInfo = __buildInfo; @@ -1250,6 +1250,7 @@ _iss sqInt statShrinkMemory; _iss sqInt statTenures; _iss sqInt edenBytes; _iss usqInt fwdTableLast; +_iss sqInt multipleBytecodeSetsActive; _iss sqInt pendingFinalizationSignals; _iss sqInt preemptionYields; _iss sqInt printSends; @@ -1261,7 +1262,6 @@ _iss sqInt tenuringThreshold; _iss sqInt externalPrimitiveTableFirstFreeIndex; _iss sqInt forceTenureFlag; _iss sqInt fullScreenFlag; -_iss sqInt multipleBytecodeSetsActive; _iss sqInt signalLowSpace; _iss sqInt statNumMaps; _iss sqInt statRootTableOverflows; @@ -1982,7 +1982,7 @@ sqInt debugCallbackInvokes; sqInt debugCallbackReturns; sqInt cannotDeferDisplayUpdates; sqInt checkedPluginName; -const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3475]"; +const char *interpreterVersion = "Open Smalltalk Stack VM [StackInterpreterPrimitives VMMaker.oscog-eem.3482]"; sqInt suppressHeartbeatFlag; char expensiveAsserts = 0; int (*showSurfaceFn)(sqIntptr_t, int, int, int, int); @@ -10229,28 +10229,15 @@ primitiveBytecodeSetsAvailable(void) if (GIV(argumentCount) > 0) { return (GIV(primFailCode) = PrimErrBadNumArgs); } - encoderNames = instantiateClassindexableSize(longAt((GIV(specialObjectsOop) + BaseHeaderSize) + ((((usqInt)(ClassArray) << (shiftForWord()))))), 3); + encoderNames = eeInstantiateSmallClassIndexformatnumSlots(ClassArrayCompactIndex, arrayFormat(), 2); valuePointer = stringForCString("EncoderForV3"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (0U << (shiftForWord())), valuePointer); valuePointer = stringForCString("EncoderForV3PlusClosures"); - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } + /* begin storePointerUnchecked:ofObject:withValue: */ longAtput((encoderNames + BaseHeaderSize) + (1U << (shiftForWord())), valuePointer); - valuePointer = stringForCString("EncoderForSistaV1"); - - /* begin storePointer:ofObject:withValue: */ - if (oopisLessThan(encoderNames, GIV(youngStart))) { - possibleRootStoreIntovalue(encoderNames, valuePointer); - } - longAtput((encoderNames + BaseHeaderSize) + (2U << (shiftForWord())), valuePointer); /* begin methodReturnValue: */ assert(!((failed()))); @@ -13183,14 +13170,13 @@ primitiveGetAttribute(void) EXPORT(sqInt) primitiveGetenv(void) { DECL_MAYBE_SQ_GLOBAL_STRUCT + char *dstPtr; char *key; - sqInt oop; - sqInt reasonCode; - sqInt result; + sqInt obj; char *sp; - char *var; + sqInt sz; + char *val; - result = 0; if (sHEAFn) { if (!(sHEAFn())) { return (GIV(primFailCode) = PrimErrInappropriate); @@ -13198,32 +13184,50 @@ primitiveGetenv(void) } /* secHasEnvironmentAccess */ - key = cStringOrNullFor(longAt(GIV(stackPointer))); - if (!key) { - if (!GIV(primFailCode)) { - return (GIV(primFailCode) = PrimErrBadArgument); - } - reasonCode = GIV(primFailCode); - /* begin primitiveFailFor: */ - return (GIV(primFailCode) = reasonCode); + /* begin stackEphemeralStringValue: */ + obj = longAt(GIV(stackPointer)); + if (!(/* isBytes: */ + ((obj & 1) == 0) + && (((((usqInt)((longAt(obj)))) >> (instFormatFieldLSB())) & 15) >= (firstByteFormat())))) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrBadArgument; + key = null; + goto l2; + } + + /* begin byteSizeOf: */ + if ((obj & 1)) { + sz = 0; + goto l1; } - var = getenv(key); - free(key); - if (var) { - result = stringForCString(var); - if (!result) { - return (GIV(primFailCode) = PrimErrNoMemory); + sz = numBytesOf(obj); + /* end byteSizeOf: */ +l1: + dstPtr = alloca(sz + 1); + if (!dstPtr) { + /* primitiveFailFor: */ + GIV(primFailCode) = PrimErrNoCMemory; + key = null; + goto l2; + } + memcpy(dstPtr, ((char *) (firstIndexableField(obj))), sz); + dstPtr[sz] = 0; + key = dstPtr; + /* end stackEphemeralStringValue: */ +l2: + if (key) { + val = getenv(key); + if (val) { + methodReturnString(val); + } + else { + /* begin methodReturnValue: */ + assert(!((failed()))); + longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), GIV(nilObj)); + GIV(stackPointer) = sp; } } - assert(GIV(primFailCode) == 0); - oop = (var - ? result - : GIV(nilObj)); - - /* begin pop:thenPush: */ - longAtput((sp = GIV(stackPointer) + (1 * BytesPerWord)), oop); - GIV(stackPointer) = sp; return 0; } @@ -15017,14 +15021,13 @@ primitiveMultipleBytecodeSetsActive(void) if (GIV(argumentCount) == 1) { if ((longAt(GIV(stackPointer))) == GIV(trueObj)) { return (GIV(primFailCode) = PrimErrUnsupported); + GIV(multipleBytecodeSetsActive) = 1; } else { - if ((longAt(GIV(stackPointer))) == GIV(falseObj)) { - GIV(multipleBytecodeSetsActive) = 0; - } - else { + if (!((longAt(GIV(stackPointer))) == GIV(falseObj))) { return (GIV(primFailCode) = PrimErrBadArgument); } + GIV(multipleBytecodeSetsActive) = 0; } } @@ -35853,7 +35856,7 @@ methodUsesPrimitiveErrorCode(sqInt aMethodObj) assert(isCompiledMethod(aMethodObj)); methodHeader = longAt((aMethodObj + BaseHeaderSize) + ((((usqInt)(HeaderIndex) << (shiftForWord()))))); return ((primitiveIndexOfMethodheader(aMethodObj, methodHeader)) > 0) - && ((LongStoreBytecode) == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ + && (LongStoreBytecode == (fetchByteofObject(((((/* begin literalCountOfMethodHeader: */ assert((methodHeader & 1)), ((((int) methodHeader)) < 0 ? ((methodHeader >> 1)) & AlternateHeaderNumLiteralsMask diff --git a/src/v3.stack/vmCallback.h b/src/v3.stack/vmCallback.h index 891c38eee7..803daee9c9 100644 --- a/src/v3.stack/vmCallback.h +++ b/src/v3.stack/vmCallback.h @@ -1,5 +1,5 @@ /* Automatically generated by - CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3475 uuid: d9ef6856-42d8-4074-bde7-82f1e1d41282 + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3482 uuid: 361722fc-fb12-4419-8419-880fe062da35 (Compiler-eem.512) */ @@ -13,21 +13,29 @@ typedef struct _VMCallbackContext { void *savedCStackPointer; void *savedCFramePointer; union { - sqIntptr_t valword; - struct { int low, high; } valleint64; - struct { int high, low; } valbeint64; - double valflt64; - struct { void *addr; sqIntptr_t size; } valstruct; - }rvs; + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + struct { sqIntptr_t a; sqIntptr_t b; } valstructll; // x86_64 Sys V ABI value struct register return types + struct { sqIntptr_t a; double b; } valstructld; + struct { double a; sqIntptr_t b; } valstructdl; + struct { double a; double b; } valstructdd; + }rvs; void *savedMostRecentCallbackContext; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; -/* The callback return type codes */ +// The callback return type codes #define retword 1 #define retword64 2 #define retdouble 3 #define retstruct 4 +#define retstructll 5 +#define retstructld 6 +#define retstructdl 7 +#define retstructdd 8