[Vm-dev] [commit][3666] CogVM source as per VMMaker.oscog-eem.1756

commits at squeakvm.org commits at squeakvm.org
Fri Apr 1 00:36:12 UTC 2016


Revision: 3666
Author:   eliot
Date:     2016-03-31 17:36:10 -0700 (Thu, 31 Mar 2016)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.1756

General:
Correct undue sign extension wile promoting 32 to 64 bits int in
fetchLong64:ofObject: This was causing trouble in non spur object memory (V3)
especially since I decided to generalize the usage of this message.

Spur:
Have WideString>>at: fail to answer an out-of-range character in the
interpreter primitive (as well as in the JIT).

Cogit:
Fix the ARM's caller-saved register mask now that we can name all the actual
registers.

Spur Cogit:
Reworked machine code generation of immutability so for common stores it
uses a single trampoline for both store checks and immutability checks.

Add a compile-time flag, CheckRememberedInTrampoline, that controls whether the
remembered check is generated in-line or in the trampoline.  If checked in the
trampoline and on 64-bits use one memory access to get the header and share the
access between the IMMUTABILITY check and the rememberedBit check.

BitBltPlugin:
BitBltSimulation is operating on bits of 32bits words, therefore it's better
to declare its operands as 'unsigned int' rather than sqInt.

On 32bits VM, this should not change anything, but on 64bits spur, it makes
this snippet work:

    | wideString source pos blt expectedWideString |
    source := #[1 64 255 14 1 64 48 251].
    expectedWideString := WideString fromByteArray: source.
    wideString := WideString new: source size // 4.
    pos := 0.
    blt := (BitBlt
        toForm: (Form new hackBits: wideString))
        sourceForm: (Form new hackBits: source).
    blt
        combinationRule: Form over;
        sourceX: 0;
        sourceY: pos // 4;
        height: wideString byteSize // 4;
        width: 4;
        destX: 0;
        destY: 0;
        copyBits.
wideString restoreEndianness.
self assert: wideString = expectedWideString

Hence it fixes loading/diffing MCZ with wide character.

Modified Paths:
--------------
    branches/Cog/build.macos32x86/makeproduct
    branches/Cog/nsspur64src/vm/cogit.h
    branches/Cog/nsspur64src/vm/cogitX64.c
    branches/Cog/nsspur64src/vm/cointerp.c
    branches/Cog/nsspur64src/vm/cointerp.h
    branches/Cog/nsspur64src/vm/gcc3x-cointerp.c
    branches/Cog/nsspursrc/vm/cogit.h
    branches/Cog/nsspursrc/vm/cogitARMv5.c
    branches/Cog/nsspursrc/vm/cogitIA32.c
    branches/Cog/nsspursrc/vm/cogitMIPSEL.c
    branches/Cog/nsspursrc/vm/cointerp.c
    branches/Cog/nsspursrc/vm/cointerp.h
    branches/Cog/nsspursrc/vm/gcc3x-cointerp.c
    branches/Cog/nsspurstack64src/vm/gcc3x-interp.c
    branches/Cog/nsspurstack64src/vm/interp.c
    branches/Cog/nsspurstacksrc/vm/gcc3x-interp.c
    branches/Cog/nsspurstacksrc/vm/interp.c
    branches/Cog/platforms/unix/vm/aio.c
    branches/Cog/spur64src/vm/cogit.h
    branches/Cog/spur64src/vm/cogitX64.c
    branches/Cog/spur64src/vm/cointerp.c
    branches/Cog/spur64src/vm/cointerp.h
    branches/Cog/spur64src/vm/gcc3x-cointerp.c
    branches/Cog/spursistasrc/vm/cogit.h
    branches/Cog/spursistasrc/vm/cogitARMv5.c
    branches/Cog/spursistasrc/vm/cogitIA32.c
    branches/Cog/spursistasrc/vm/cogitMIPSEL.c
    branches/Cog/spursistasrc/vm/cointerp.c
    branches/Cog/spursistasrc/vm/cointerp.h
    branches/Cog/spursistasrc/vm/gcc3x-cointerp.c
    branches/Cog/spursrc/vm/cogit.h
    branches/Cog/spursrc/vm/cogitARMv5.c
    branches/Cog/spursrc/vm/cogitIA32.c
    branches/Cog/spursrc/vm/cogitMIPSEL.c
    branches/Cog/spursrc/vm/cointerp.c
    branches/Cog/spursrc/vm/cointerp.h
    branches/Cog/spursrc/vm/gcc3x-cointerp.c
    branches/Cog/spurstack64src/vm/gcc3x-interp.c
    branches/Cog/spurstack64src/vm/interp.c
    branches/Cog/spurstacksrc/vm/gcc3x-interp.c
    branches/Cog/spurstacksrc/vm/interp.c
    branches/Cog/src/plugins/BitBltPlugin/BitBltPlugin.c
    branches/Cog/src/vm/cogit.h
    branches/Cog/src/vm/cogitARMv5.c
    branches/Cog/src/vm/cogitIA32.c
    branches/Cog/src/vm/cogitMIPSEL.c
    branches/Cog/src/vm/cointerp.c
    branches/Cog/src/vm/cointerp.h
    branches/Cog/src/vm/cointerpmt.c
    branches/Cog/src/vm/cointerpmt.h
    branches/Cog/src/vm/gcc3x-cointerp.c
    branches/Cog/src/vm/gcc3x-cointerpmt.c
    branches/Cog/stacksrc/vm/gcc3x-interp.c
    branches/Cog/stacksrc/vm/interp.c

Added Paths:
-----------
    branches/Cog/build.macos32x86/makeproductclean

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

Modified: branches/Cog/build.macos32x86/makeproduct
===================================================================
--- branches/Cog/build.macos32x86/makeproduct	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/build.macos32x86/makeproduct	2016-04-01 00:36:10 UTC (rev 3666)
@@ -1,6 +1,6 @@
 #!/bin/bash
 trap 'exit 2' HUP INT PIPE TERM
-PRODUCTDIRS="newspeak.cog.spur pharo.cog.spur squeak.cog.spur squeak.cog.v3"
+PRODUCTDIRS="newspeak.cog.spur pharo.cog.spur squeak.cog.spur squeak.cog.v3 squeak.cog.spur.immutability"
 for d in $PRODUCTDIRS; do
 	if test -d "$d"; then
 		(cd ./$d;./mvm -A)

Copied: branches/Cog/build.macos32x86/makeproductclean (from rev 3660, branches/Cog/build.macos32x86/makeproduct)
===================================================================
--- branches/Cog/build.macos32x86/makeproductclean	                        (rev 0)
+++ branches/Cog/build.macos32x86/makeproductclean	2016-04-01 00:36:10 UTC (rev 3666)
@@ -0,0 +1,19 @@
+#!/bin/bash
+trap 'exit 2' HUP INT PIPE TERM
+PRODUCTDIRS="newspeak.cog.spur pharo.cog.spur squeak.cog.spur squeak.cog.v3 squeak.cog.spur.immutability"
+for d in $PRODUCTDIRS; do
+	if test -d "$d"; then
+		(cd ./$d;echo $d;make cleanall)
+	fi
+done
+for d in $PRODUCTDIRS; do
+	if test -d "$d"; then
+		(cd ./$d;./mvm -A)
+	else
+		echo no $d directory found
+	fi
+done
+echo no news is good news...
+for d in $PRODUCTDIRS; do
+	test -d $d && grep -w error: $d/LOG*
+done

Modified: branches/Cog/nsspur64src/vm/cogit.h
===================================================================
--- branches/Cog/nsspur64src/vm/cogit.h	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/nsspur64src/vm/cogit.h	2016-04-01 00:36:10 UTC (rev 3666)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CCodeGenerator VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
  */
 
 

Modified: branches/Cog/nsspur64src/vm/cogitX64.c
===================================================================
--- branches/Cog/nsspur64src/vm/cogitX64.c	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/nsspur64src/vm/cogitX64.c	2016-04-01 00:36:10 UTC (rev 3666)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CCodeGenerator VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	StackToRegisterMappingCogit VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288 " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7 " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -47,6 +47,9 @@
 #define Call 6
 #define CallFull 7
 #define CDQ 116
+#if !defined(CheckRememberedInTrampoline) /* Allow this to be overridden on the compiler command line */
+# define CheckRememberedInTrampoline 0
+#endif
 #define ClassArrayCompactIndex 51
 #define ClassBlockClosureCompactIndex 37
 #define ClassFloatCompactIndex 34
@@ -219,6 +222,7 @@
 #define NumOopsPerNSC 6
 #define NumSendTrampolines 4
 #define NumSpecialSelectors 32
+#define NumStoreTrampolines 5
 #define NumTrampolines 72
 #define OrCqR 98
 #define OrCwR 106
@@ -542,12 +546,10 @@
 static sqInt NoDbgRegParms genReturnTrampolineForcalledarg(void *aRoutine, char *aString, sqInt regOrConst0);
 static sqInt NoDbgRegParms genSmalltalkToCStackSwitch(sqInt pushLinkReg);
 static sqInt NoDbgRegParms genTrampolineForcalled(void *aRoutine, char *aString);
-static sqInt NoDbgRegParms genTrampolineForcalledargargarg(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regOrConst1, sqInt regOrConst2);
 static sqInt NoDbgRegParms genTrampolineForcalledargargargresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regOrConst1, sqInt regOrConst2, sqInt resultReg);
 static sqInt NoDbgRegParms genTrampolineForcalledargargregsToSave(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regOrConst1, sqInt regMask);
 static sqInt NoDbgRegParms genTrampolineForcalledargargresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regOrConst1, sqInt resultReg);
 static sqInt NoDbgRegParms genTrampolineForcalledargregsToSave(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regMask);
-static sqInt NoDbgRegParms genTrampolineForcalledargregsToSaveresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regMask, sqInt resultReg);
 static sqInt NoDbgRegParms genTrampolineForcalledargresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt resultReg);
 static sqInt NoDbgRegParms genTrampolineForcallednumArgsargargargargregsToSavepushLinkRegresultRegappendOpcodes(void *aRoutine, char *trampolineName, sqInt numArgs, sqInt regOrConst0, sqInt regOrConst1, sqInt regOrConst2, sqInt regOrConst3, sqInt regMask, sqInt pushLinkReg, sqInt resultRegOrNone, sqInt appendBoolean);
 static sqInt NoDbgRegParms genTrampolineForcalledregsToSave(void *aRoutine, char *aString, sqInt regMask);
@@ -650,6 +652,7 @@
 extern sqInt traceLinkedSendOffset(void);
 static sqInt NoDbgRegParms trampolineArgConstant(sqInt booleanOrInteger);
 static char * NoDbgRegParms trampolineNamenumArgs(char *routinePrefix, sqInt numArgs);
+static char * NoDbgRegParms trampolineNamenumArgslimit(char *routinePrefix, int numArgs, sqInt argsLimit);
 static char * NoDbgRegParms trampolineNamenumRegArgs(char *routinePrefix, sqInt numArgs);
 static sqInt unknownBytecode(void);
 extern void unlinkAllSends(void);
@@ -797,6 +800,7 @@
 static sqInt NoDbgRegParms checkValidOopReference(sqInt anOop);
 static sqInt NoDbgRegParms couldBeObject(sqInt literal);
 static sqInt NoDbgRegParms genActiveContextTrampolineLargeinBlockcalled(sqInt isLarge, sqInt isInBlock, char *aString);
+static AbstractInstruction * NoDbgRegParms genCheckRememberedBitOfscratch(sqInt objReg, sqInt scratchReg);
 static sqInt NoDbgRegParms genConvertCharacterToCodeInReg(sqInt reg);
 static sqInt NoDbgRegParms genConvertIntegerToCharacterInReg(sqInt reg);
 static sqInt NoDbgRegParms genCreateClosureAtnumArgsnumCopiedcontextNumArgslargeinBlock(sqInt bcpc, sqInt numArgs, sqInt numCopied, sqInt ctxtNumArgs, sqInt isLargeCtxt, sqInt isInBlock);
@@ -819,14 +823,11 @@
 static sqInt NoDbgRegParms genGetFormatOfintoleastSignificantHalfOfBaseHeaderIntoScratch(sqInt sourceReg, sqInt destReg, sqInt scratchRegOrNone);
 static sqInt NoDbgRegParms genGetNumSlotsOfinto(sqInt srcReg, sqInt destReg);
 static sqInt NoDbgRegParms genGetRawSlotSizeOfNonImminto(sqInt sourceReg, sqInt destReg);
+static AbstractInstruction * NoDbgRegParms genJumpImmediate(sqInt aRegister);
 #if IMMUTABILITY
-static AbstractInstruction * NoDbgRegParms genJumpBaseHeaderImmutable(sqInt baseHeaderReg);
+static AbstractInstruction * NoDbgRegParms genJumpImmutablescratchReg(sqInt sourceReg, sqInt scratchReg);
 #endif /* IMMUTABILITY */
 #if IMMUTABILITY
-static AbstractInstruction * NoDbgRegParms genJumpBaseHeaderMutable(sqInt baseHeaderReg);
-#endif /* IMMUTABILITY */
-static AbstractInstruction * NoDbgRegParms genJumpImmediate(sqInt aRegister);
-#if IMMUTABILITY
 static AbstractInstruction * NoDbgRegParms genJumpMutablescratchReg(sqInt sourceReg, sqInt scratchReg);
 #endif /* IMMUTABILITY */
 static sqInt NoDbgRegParms genNewArrayOfSizeinitialized(sqInt size, sqInt initialized);
@@ -840,6 +841,18 @@
 static sqInt NoDbgRegParms genStoreCheckReceiverRegvalueRegscratchReginFrame(sqInt destReg, sqInt valueReg, sqInt scratchReg, sqInt inFrame);
 static sqInt NoDbgRegParms genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt inFrame, sqInt needsStoreCheck);
 static sqInt NoDbgRegParms genStoreSourceRegslotIndexintoNewObjectInDestReg(sqInt sourceReg, sqInt index, sqInt destReg);
+#if IMMUTABILITY
+static sqInt NoDbgRegParms genStoreTrampolineCalledinstVarIndex(char *trampolineName, sqInt instVarIndex);
+#endif /* IMMUTABILITY */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms genStoreWithImmutabilityAndStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needRestoreRcvr);
+#endif /* IMMUTABILITY */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms genStoreWithImmutabilityButNoStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needRestoreRcvr);
+#endif /* IMMUTABILITY */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms genStoreWithImmutabilityCheckSourceRegslotIndexdestRegscratchRegneedsStoreCheckneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needsStoreCheck, sqInt needRestoreRcvr);
+#endif /* IMMUTABILITY */
 static sqInt getActiveContextAllocatesInMachineCode(void);
 static sqInt NoDbgRegParms inlineCacheTagIsYoung(sqInt cacheTag);
 static AbstractInstruction * NoDbgRegParms jumpNotCharacterUnsignedValueInRegister(sqInt reg);
@@ -1180,7 +1193,6 @@
 void (*ceCallCogCodePopReceiverArg0Regs)(void);
 void (*ceCallCogCodePopReceiverArg1Arg0Regs)(void);
 void (*ceCallCogCodePopReceiverReg)(void);
-static sqInt ceCannotAssignToWithIndexTrampoline;
 sqInt ceCannotResumeTrampoline;
 void (*ceCaptureCStackPointers)(void);
 static unsigned long (*ceCheckFeaturesFunction)(void);
@@ -1209,6 +1221,9 @@
 static sqInt ceStoreCheckContextReceiverTrampoline;
 static sqInt ceStoreCheckTrampoline;
 static sqInt ceStoreContextInstVarTrampoline;
+#if IMMUTABILITY
+sqInt ceStoreTrampolines[5];
+#endif
 static sqInt ceTraceBlockActivationTrampoline;
 static sqInt ceTraceLinkedSendTrampoline;
 static sqInt ceTraceStoreTrampoline;
@@ -3636,7 +3651,7 @@
 closedPICRefersToUnmarkedObject(CogMethod *cPIC)
 {
     sqInt i;
-    sqInt object;
+    usqInt object;
     sqInt pc;
 
 	if (!((isImmediate((cPIC->selector)))
@@ -5833,12 +5848,12 @@
 generateMapAtstart(sqInt addressOrNull, sqInt startAddress)
 {
     unsigned char annotation;
-    usqInt delta;
+    sqInt delta;
     sqInt i;
     AbstractInstruction *instruction;
     sqInt length;
-    usqInt location;
-    usqInt mapEntry;
+    sqInt location;
+    sqInt mapEntry;
     sqInt maxDelta;
     usqInt mcpc;
 
@@ -6335,18 +6350,6 @@
 }
 
 
-/*	Generate a trampoline with three arguments.
-	Hack: a negative value indicates an abstract register, a non-negative
-	value indicates a constant. */
-
-	/* Cogit>>#genTrampolineFor:called:arg:arg:arg: */
-static sqInt NoDbgRegParms
-genTrampolineForcalledargargarg(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regOrConst1, sqInt regOrConst2)
-{
-	return genTrampolineForcallednumArgsargargargargregsToSavepushLinkRegresultRegappendOpcodes(aRoutine, aString, 3, regOrConst0, regOrConst1, regOrConst2, null, 0, 1, NoReg, 0);
-}
-
-
 /*	Generate a trampoline with two arguments that answers a result.
 	Hack: a negative value indicates an abstract register, a non-negative
 	value indicates a constant. */
@@ -6399,18 +6402,6 @@
 	Hack: a negative value indicates an abstract register, a non-negative
 	value indicates a constant. */
 
-	/* Cogit>>#genTrampolineFor:called:arg:regsToSave:result: */
-static sqInt NoDbgRegParms
-genTrampolineForcalledargregsToSaveresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt regMask, sqInt resultReg)
-{
-	return genTrampolineForcallednumArgsargargargargregsToSavepushLinkRegresultRegappendOpcodes(aRoutine, aString, 1, regOrConst0, null, null, null, regMask, 1, resultReg, 0);
-}
-
-
-/*	Generate a trampoline with one argument that answers a result.
-	Hack: a negative value indicates an abstract register, a non-negative
-	value indicates a constant. */
-
 	/* Cogit>>#genTrampolineFor:called:arg:result: */
 static sqInt NoDbgRegParms
 genTrampolineForcalledargresult(void *aRoutine, char *aString, sqInt regOrConst0, sqInt resultReg)
@@ -9250,6 +9241,22 @@
 	return theString;
 }
 
+
+/*	Malloc a string with the contents for the trampoline table */
+
+	/* Cogit>>#trampolineName:numArgs:limit: */
+static char * NoDbgRegParms
+trampolineNamenumArgslimit(char *routinePrefix, int numArgs, sqInt argsLimit)
+{
+    char *theString;
+
+	theString = malloc((strlen(routinePrefix)) + 6);
+	sprintf(theString, "%s%cArgs", routinePrefix, (numArgs <= argsLimit
+		? '0' + numArgs
+		: 'N'));
+	return theString;
+}
+
 	/* Cogit>>#trampolineName:numRegArgs: */
 static char * NoDbgRegParms
 trampolineNamenumRegArgs(char *routinePrefix, sqInt numArgs)
@@ -12771,6 +12778,7 @@
     AbstractInstruction *anInstruction15;
     AbstractInstruction *anInstruction16;
     AbstractInstruction *anInstruction17;
+    AbstractInstruction *anInstruction18;
     AbstractInstruction *anInstruction2;
     AbstractInstruction *anInstruction3;
     AbstractInstruction *anInstruction4;
@@ -12808,6 +12816,7 @@
     sqInt quickConstant4;
     sqInt quickConstant5;
     sqInt quickConstant6;
+    sqInt quickConstant7;
 
 	/* begin genLoadArgAtDepth:into: */
 	assert(1 < (numRegArgs()));
@@ -12822,7 +12831,12 @@
 	
 #  if IMMUTABILITY
 	genGetFormatOfintoleastSignificantHalfOfBaseHeaderIntoScratch(ReceiverResultReg, (formatReg = SendNumArgsReg), TempReg);
-	jumpImmutable = genJumpBaseHeaderImmutable(TempReg);
+	/* begin genJumpBaseHeaderImmutable: */
+	quickConstant7 = immutableBitMask();
+	/* begin gen:quickConstant:operand: */
+	anInstruction18 = genoperandoperand(TstCqR, quickConstant7, TempReg);
+	/* begin JumpNonZero: */
+	jumpImmutable = genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
 
 #  else /* IMMUTABILITY */
 	genGetFormatOfintoleastSignificantHalfOfBaseHeaderIntoScratch(ReceiverResultReg, (formatReg = SendNumArgsReg), NoReg);
@@ -14115,6 +14129,7 @@
     AbstractInstruction *anInstruction10;
     AbstractInstruction *anInstruction11;
     AbstractInstruction *anInstruction12;
+    AbstractInstruction *anInstruction13;
     AbstractInstruction *anInstruction2;
     AbstractInstruction *anInstruction3;
     AbstractInstruction *anInstruction4;
@@ -14142,6 +14157,7 @@
     sqInt quickConstant2;
     sqInt quickConstant3;
     sqInt quickConstant4;
+    sqInt quickConstant5;
 
 	/* begin genLoadArgAtDepth:into: */
 	assert(1 < (numRegArgs()));
@@ -14155,7 +14171,12 @@
 	
 #  if IMMUTABILITY
 	genGetFormatOfintoleastSignificantHalfOfBaseHeaderIntoScratch(ReceiverResultReg, (formatReg = SendNumArgsReg), TempReg);
-	jumpImmutable = genJumpBaseHeaderImmutable(TempReg);
+	/* begin genJumpBaseHeaderImmutable: */
+	quickConstant5 = immutableBitMask();
+	/* begin gen:quickConstant:operand: */
+	anInstruction13 = genoperandoperand(TstCqR, quickConstant5, TempReg);
+	/* begin JumpNonZero: */
+	jumpImmutable = genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
 
 #  else /* IMMUTABILITY */
 	genGetFormatOfintoleastSignificantHalfOfBaseHeaderIntoScratch(ReceiverResultReg, (formatReg = SendNumArgsReg), NoReg);
@@ -14534,6 +14555,32 @@
 	return startAddress;
 }
 
+
+/*	Check the remembered bit of the object in objReg; answer the jump taken if
+	the bit is already set.
+	Only need to fetch the byte containing it, which reduces the size of the
+	mask constant.
+ */
+
+	/* CogObjectRepresentationForSpur>>#genCheckRememberedBitOf:scratch: */
+static AbstractInstruction * NoDbgRegParms
+genCheckRememberedBitOfscratch(sqInt objReg, sqInt scratchReg)
+{
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    sqInt mask;
+    sqInt rememberedBitByteOffset;
+
+	rememberedBitByteOffset = (rememberedBitShift()) / 8;
+	mask = 1LL << ((rememberedBitShift()) % 8);
+	/* begin MoveMb:r:R: */
+	anInstruction = genoperandoperandoperand(MoveMbrR, rememberedBitByteOffset, objReg, scratchReg);
+	/* begin TstCq:R: */
+	anInstruction1 = genoperandoperand(TstCqR, mask, scratchReg);
+	/* begin JumpNonZero: */
+	return genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
+}
+
 	/* CogObjectRepresentationForSpur>>#genConvertCharacterToCodeInReg: */
 static sqInt NoDbgRegParms
 genConvertCharacterToCodeInReg(sqInt reg)
@@ -14782,15 +14829,28 @@
 static void
 generateObjectRepresentationTrampolines(void)
 {
+    sqInt instVarIndex;
+    AbstractInstruction *jumpSC;
+
 	
 #  if IMMUTABILITY
+	for (instVarIndex = 0; instVarIndex < NumStoreTrampolines; instVarIndex += 1) {
+		ceStoreTrampolines[instVarIndex] = (genStoreTrampolineCalledinstVarIndex(trampolineNamenumArgslimit("ceStoreTrampoline", instVarIndex, NumStoreTrampolines - 2), instVarIndex));
+	}
 
-	/* c.f. genImmutableCheck:slotIndex:sourceReg:scratchReg:popBoolean:needRestoreRcvr: */
-	ceCannotAssignToWithIndexTrampoline = genTrampolineForcalledargargarg(ceCannotAssignTowithIndexvalueToAssign, "ceCannotAssignToWithIndexTrampoline", ReceiverResultReg, TempReg, ClassReg);
-
 #  endif /* IMMUTABILITY */
 
-	ceStoreCheckTrampoline = genTrampolineForcalledargregsToSaveresult(remember, "ceStoreCheckTrampoline", ReceiverResultReg, (((callerSavedRegMask()) | (1LL << ReceiverResultReg)) - (1LL << ReceiverResultReg)), returnRegForStoreCheck());
+	/* begin genStoreCheckTrampoline */
+	if (CheckRememberedInTrampoline) {
+		zeroOpcodeIndex();
+		jumpSC = genCheckRememberedBitOfscratch(ReceiverResultReg, RAX);
+		assert(((jumpSC->opcode)) == JumpNonZero);
+		(jumpSC->opcode = JumpZero);
+		/* begin RetN: */
+		genoperand(RetN, 0);
+		jmpTarget(jumpSC, gLabel());
+	}
+	ceStoreCheckTrampoline = genTrampolineForcallednumArgsargargargargregsToSavepushLinkRegresultRegappendOpcodes(remember, "ceStoreCheckTrampoline", 1, ReceiverResultReg, null, null, null, (((callerSavedRegMask()) | (1LL << ReceiverResultReg)) - (1LL << ReceiverResultReg)), 1, returnRegForStoreCheck(), CheckRememberedInTrampoline);
 	ceStoreCheckContextReceiverTrampoline = genStoreCheckContextReceiverTrampoline();
 	ceScheduleScavengeTrampoline = genTrampolineForcalledregsToSave(ceScheduleScavenge, "ceScheduleScavengeTrampoline", callerSavedRegMask());
 	ceSmallActiveContextInMethodTrampoline = genActiveContextTrampolineLargeinBlockcalled(0, 0, "ceSmallMethodContext");
@@ -15340,60 +15400,40 @@
 	return 0;
 }
 
-
-/*	baseHeader holds at least the least significant 32 bits of the object */
-
-	/* CogObjectRepresentationForSpur>>#genJumpBaseHeaderImmutable: */
-#if IMMUTABILITY
+	/* CogObjectRepresentationForSpur>>#genJumpImmediate: */
 static AbstractInstruction * NoDbgRegParms
-genJumpBaseHeaderImmutable(sqInt baseHeaderReg)
+genJumpImmediate(sqInt aRegister)
 {
     AbstractInstruction *anInstruction;
     sqInt quickConstant;
 
 	/* begin TstCq:R: */
-	quickConstant = immutableBitMask();
+	quickConstant = tagMask();
 	/* begin gen:quickConstant:operand: */
-	anInstruction = genoperandoperand(TstCqR, quickConstant, baseHeaderReg);
+	anInstruction = genoperandoperand(TstCqR, quickConstant, aRegister);
 	/* begin JumpNonZero: */
 	return genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
 }
-#endif /* IMMUTABILITY */
 
-
-/*	baseHeader holds at least the least significant 32 bits of the object */
-
-	/* CogObjectRepresentationForSpur>>#genJumpBaseHeaderMutable: */
+	/* CogObjectRepresentationForSpur>>#genJumpImmutable:scratchReg: */
 #if IMMUTABILITY
 static AbstractInstruction * NoDbgRegParms
-genJumpBaseHeaderMutable(sqInt baseHeaderReg)
+genJumpImmutablescratchReg(sqInt sourceReg, sqInt scratchReg)
 {
     AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
     sqInt quickConstant;
 
-	/* begin TstCq:R: */
+	/* begin MoveMw:r:R: */
+	anInstruction = genoperandoperandoperand(MoveMwrR, 0, sourceReg, scratchReg);
+	/* begin genJumpBaseHeaderImmutable: */
 	quickConstant = immutableBitMask();
 	/* begin gen:quickConstant:operand: */
-	anInstruction = genoperandoperand(TstCqR, quickConstant, baseHeaderReg);
-	/* begin JumpZero: */
-	return genConditionalBranchoperand(JumpZero, ((sqInt)0));
-}
-#endif /* IMMUTABILITY */
-
-	/* CogObjectRepresentationForSpur>>#genJumpImmediate: */
-static AbstractInstruction * NoDbgRegParms
-genJumpImmediate(sqInt aRegister)
-{
-    AbstractInstruction *anInstruction;
-    sqInt quickConstant;
-
-	/* begin TstCq:R: */
-	quickConstant = tagMask();
-	/* begin gen:quickConstant:operand: */
-	anInstruction = genoperandoperand(TstCqR, quickConstant, aRegister);
+	anInstruction1 = genoperandoperand(TstCqR, quickConstant, scratchReg);
 	/* begin JumpNonZero: */
 	return genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
 }
+#endif /* IMMUTABILITY */
 
 	/* CogObjectRepresentationForSpur>>#genJumpMutable:scratchReg: */
 #if IMMUTABILITY
@@ -15401,10 +15441,17 @@
 genJumpMutablescratchReg(sqInt sourceReg, sqInt scratchReg)
 {
     AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    sqInt quickConstant;
 
 	/* begin MoveMw:r:R: */
 	anInstruction = genoperandoperandoperand(MoveMwrR, 0, sourceReg, scratchReg);
-	return genJumpBaseHeaderMutable(scratchReg);
+	/* begin genJumpBaseHeaderMutable: */
+	quickConstant = immutableBitMask();
+	/* begin gen:quickConstant:operand: */
+	anInstruction1 = genoperandoperand(TstCqR, quickConstant, scratchReg);
+	/* begin JumpZero: */
+	return genConditionalBranchoperand(JumpZero, ((sqInt)0));
 }
 #endif /* IMMUTABILITY */
 
@@ -15888,14 +15935,10 @@
 {
     AbstractInstruction *abstractInstruction;
     AbstractInstruction *anInstruction;
-    AbstractInstruction *anInstruction1;
-    AbstractInstruction *anInstruction2;
     AbstractInstruction *jmpAlreadyRemembered;
     AbstractInstruction *jmpDestYoung;
     AbstractInstruction *jmpImmediate;
     AbstractInstruction *jmpSourceOld;
-    sqInt mask;
-    sqInt rememberedBitByteOffset;
     sqInt wordConstant;
 
 
@@ -15915,14 +15958,9 @@
 	genoperandoperand(CmpRR, scratchReg, valueReg);
 	/* begin JumpAboveOrEqual: */
 	jmpSourceOld = genConditionalBranchoperand(JumpAboveOrEqual, ((sqInt)0));
-	rememberedBitByteOffset = (rememberedBitShift()) / 8;
-	mask = 1LL << ((rememberedBitShift()) % 8);
-	/* begin MoveMb:r:R: */
-	anInstruction1 = genoperandoperandoperand(MoveMbrR, rememberedBitByteOffset, destReg, scratchReg);
-	/* begin AndCq:R: */
-	anInstruction2 = genoperandoperand(AndCqR, mask, scratchReg);
-	/* begin JumpNonZero: */
-	jmpAlreadyRemembered = genConditionalBranchoperand(JumpNonZero, ((sqInt)0));
+	if (!CheckRememberedInTrampoline) {
+		jmpAlreadyRemembered = genCheckRememberedBitOfscratch(destReg, scratchReg);
+	}
 	assert(destReg == ReceiverResultReg);
 	/* begin evaluateTrampolineCallBlock:protectLinkRegIfNot: */
 	if (inFrame) {
@@ -15938,19 +15976,28 @@
 
 
 	}
-	jmpTarget(jmpImmediate, jmpTarget(jmpDestYoung, jmpTarget(jmpSourceOld, jmpTarget(jmpAlreadyRemembered, gLabel()))));
+	jmpTarget(jmpImmediate, jmpTarget(jmpDestYoung, jmpTarget(jmpSourceOld, gLabel())));
+	if (!CheckRememberedInTrampoline) {
+		jmpTarget(jmpAlreadyRemembered, getJmpTarget(jmpSourceOld));
+	}
 	return 0;
 }
 
-
-/*	do the store */
-
 	/* CogObjectRepresentationForSpur>>#genStoreSourceReg:slotIndex:destReg:scratchReg:inFrame:needsStoreCheck: */
 static sqInt NoDbgRegParms
 genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt inFrame, sqInt needsStoreCheck)
 {
+    AbstractInstruction *abstractInstruction;
     AbstractInstruction *anInstruction;
 
+	/* begin genTraceStores */
+	if (traceStores > 0) {
+		/* begin MoveR:R: */
+		genoperandoperand(MoveRR, ClassReg, TempReg);
+		/* begin CallRT: */
+		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
+		(abstractInstruction->annotation = IsRelativeCall);
+	}
 	/* begin MoveR:Mw:r: */
 	anInstruction = genoperandoperandoperand(MoveRMwr, sourceReg, (index * BytesPerWord) + BaseHeaderSize, destReg);
 	if (needsStoreCheck) {
@@ -15977,6 +16024,214 @@
 }
 
 
+/*	Convention:
+	- RcvrResultReg holds the object mutated.
+	If immutability failure:
+	- TempReg holds the instance variable index mutated 
+	if instVarIndex > numDedicatedStoreTrampoline
+	- ClassReg holds the value to store
+	Registers are not lived across this trampoline as the 
+	immutability failure may need new stack frames. */
+
+	/* CogObjectRepresentationForSpur>>#genStoreTrampolineCalled:instVarIndex: */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms
+genStoreTrampolineCalledinstVarIndex(char *trampolineName, sqInt instVarIndex)
+{
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *jumpRC;
+    AbstractInstruction *jumpSC;
+    sqInt quickConstant;
+
+	zeroOpcodeIndex();
+	jumpSC = genJumpMutablescratchReg(ReceiverResultReg, SendNumArgsReg);
+	compileTrampolineFornumArgsargargargargregsToSavepushLinkRegresultReg(ceCannotAssignTowithIndexvalueToAssign, 3, ReceiverResultReg, (instVarIndex < (NumStoreTrampolines - 1)
+		? (/* begin trampolineArgConstant: */
+			assert(instVarIndex >= 0),
+			-2 - instVarIndex)
+		: TempReg), ClassReg, null, 0, 1, NoReg);
+	jmpTarget(jumpSC, gLabel());
+	if (CheckRememberedInTrampoline) {
+		/* begin TstCq:R: */
+		quickConstant = 1LL << (rememberedBitShift());
+		/* begin gen:quickConstant:operand: */
+		anInstruction = genoperandoperand(TstCqR, quickConstant, SendNumArgsReg);
+		/* begin JumpZero: */
+		jumpRC = genConditionalBranchoperand(JumpZero, ((sqInt)0));
+		/* begin RetN: */
+		genoperand(RetN, 0);
+
+		jmpTarget(jumpRC, gLabel());
+	}
+	return genTrampolineForcallednumArgsargargargargregsToSavepushLinkRegresultRegappendOpcodes(remember, trampolineName, 1, ReceiverResultReg, null, null, null, 0, 1, NoReg, 1);
+}
+#endif /* IMMUTABILITY */
+
+
+/*	Store check code is duplicated to use a single trampoline */
+
+	/* CogObjectRepresentationForSpur>>#genStoreWithImmutabilityAndStoreCheckSourceReg:slotIndex:destReg:scratchReg:needRestoreRcvr: */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms
+genStoreWithImmutabilityAndStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needRestoreRcvr)
+{
+    AbstractInstruction *abstractInstruction;
+    AbstractInstruction *abstractInstruction1;
+    AbstractInstruction *abstractInstruction2;
+    AbstractInstruction *abstractInstruction3;
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    AbstractInstruction *anInstruction2;
+    AbstractInstruction *immutableJump;
+    AbstractInstruction *jmpAlreadyRemembered;
+    AbstractInstruction *jmpDestYoung;
+    AbstractInstruction *jmpImmediate;
+    AbstractInstruction *jmpSourceOld;
+    sqInt wordConstant;
+
+	immutableJump = genJumpImmutablescratchReg(destReg, scratchReg);
+	/* begin genTraceStores */
+	if (traceStores > 0) {
+		/* begin MoveR:R: */
+		genoperandoperand(MoveRR, ClassReg, TempReg);
+		/* begin CallRT: */
+		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
+		(abstractInstruction->annotation = IsRelativeCall);
+	}
+	/* begin MoveR:Mw:r: */
+	anInstruction = genoperandoperandoperand(MoveRMwr, sourceReg, (index * BytesPerWord) + BaseHeaderSize, destReg);
+
+	/* Get the old/new boundary in scratchReg */
+	jmpImmediate = genJumpImmediate(sourceReg);
+	/* begin MoveCw:R: */
+	wordConstant = storeCheckBoundary();
+	/* begin gen:literal:operand: */
+	anInstruction1 = genoperandoperand(MoveCwR, wordConstant, scratchReg);
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, scratchReg, destReg);
+	/* begin JumpBelow: */
+	jmpDestYoung = genConditionalBranchoperand(JumpBelow, ((sqInt)0));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, scratchReg, sourceReg);
+	/* begin JumpAboveOrEqual: */
+	jmpSourceOld = genConditionalBranchoperand(JumpAboveOrEqual, ((sqInt)0));
+	if (!CheckRememberedInTrampoline) {
+		jmpAlreadyRemembered = genCheckRememberedBitOfscratch(destReg, scratchReg);
+	}
+	jmpTarget(immutableJump, gLabel());
+	/* begin genStoreTrampolineCall: */
+	if (index >= (NumStoreTrampolines - 1)) {
+		/* begin MoveCq:R: */
+		anInstruction2 = genoperandoperand(MoveCqR, index, TempReg);
+		/* begin CallRT: */
+		abstractInstruction1 = genoperand(Call, ceStoreTrampolines[NumStoreTrampolines - 1]);
+		(abstractInstruction1->annotation = IsRelativeCall);
+	}
+	else {
+		/* begin CallRT: */
+		abstractInstruction2 = genoperand(Call, ceStoreTrampolines[index]);
+		(abstractInstruction2->annotation = IsRelativeCall);
+	}
+	/* begin annotateBytecode: */
+	abstractInstruction3 = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	(abstractInstruction3->annotation = HasBytecodePC);
+	if (needRestoreRcvr) {
+		/* begin putSelfInReceiverResultReg */
+		storeToReg((&simSelf), ReceiverResultReg);
+	}
+	jmpTarget(jmpImmediate, jmpTarget(jmpDestYoung, jmpTarget(jmpSourceOld, gLabel())));
+	if (!CheckRememberedInTrampoline) {
+		jmpTarget(jmpAlreadyRemembered, getJmpTarget(jmpSourceOld));
+	}
+	return 0;
+}
+#endif /* IMMUTABILITY */
+
+
+/*	Gen an immutability check with no store check (e.g. assigning an immediate
+	literal) 
+ */
+/*	imm check has its own trampoline */
+
+	/* CogObjectRepresentationForSpur>>#genStoreWithImmutabilityButNoStoreCheckSourceReg:slotIndex:destReg:scratchReg:needRestoreRcvr: */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms
+genStoreWithImmutabilityButNoStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needRestoreRcvr)
+{
+    AbstractInstruction *abstractInstruction;
+    AbstractInstruction *abstractInstruction1;
+    AbstractInstruction *abstractInstruction2;
+    AbstractInstruction *abstractInstruction3;
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    AbstractInstruction *immutabilityFailure;
+    AbstractInstruction *mutableJump;
+
+	mutableJump = genJumpMutablescratchReg(destReg, scratchReg);
+	/* begin genStoreTrampolineCall: */
+	if (index >= (NumStoreTrampolines - 1)) {
+		/* begin MoveCq:R: */
+		anInstruction1 = genoperandoperand(MoveCqR, index, TempReg);
+		/* begin CallRT: */
+		abstractInstruction1 = genoperand(Call, ceStoreTrampolines[NumStoreTrampolines - 1]);
+		(abstractInstruction1->annotation = IsRelativeCall);
+	}
+	else {
+		/* begin CallRT: */
+		abstractInstruction2 = genoperand(Call, ceStoreTrampolines[index]);
+		(abstractInstruction2->annotation = IsRelativeCall);
+	}
+	/* begin annotateBytecode: */
+	abstractInstruction3 = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	(abstractInstruction3->annotation = HasBytecodePC);
+	if (needRestoreRcvr) {
+		/* begin putSelfInReceiverResultReg */
+		storeToReg((&simSelf), ReceiverResultReg);
+	}
+	/* begin Jump: */
+	immutabilityFailure = genoperand(Jump, ((sqInt)0));
+	jmpTarget(mutableJump, gLabel());
+	/* begin genTraceStores */
+	if (traceStores > 0) {
+		/* begin MoveR:R: */
+		genoperandoperand(MoveRR, ClassReg, TempReg);
+		/* begin CallRT: */
+		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
+		(abstractInstruction->annotation = IsRelativeCall);
+	}
+	/* begin MoveR:Mw:r: */
+	anInstruction = genoperandoperandoperand(MoveRMwr, sourceReg, (index * BytesPerWord) + BaseHeaderSize, destReg);
+	jmpTarget(immutabilityFailure, gLabel());
+	return 0;
+}
+#endif /* IMMUTABILITY */
+
+
+/*	We know there is a frame as immutability check requires a frame */
+/*	needRestoreRcvr has to be true to keep RcvrResultReg live with the
+	receiver in it across the trampoline
+ */
+/*	Trampoline convention... */
+
+	/* CogObjectRepresentationForSpur>>#genStoreWithImmutabilityCheckSourceReg:slotIndex:destReg:scratchReg:needsStoreCheck:needRestoreRcvr: */
+#if IMMUTABILITY
+static sqInt NoDbgRegParms
+genStoreWithImmutabilityCheckSourceRegslotIndexdestRegscratchRegneedsStoreCheckneedRestoreRcvr(sqInt sourceReg, sqInt index, sqInt destReg, sqInt scratchReg, sqInt needsStoreCheck, sqInt needRestoreRcvr)
+{
+	assert(destReg == ReceiverResultReg);
+	assert(scratchReg == TempReg);
+	assert(sourceReg == ClassReg);
+	if (needsStoreCheck) {
+		genStoreWithImmutabilityAndStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sourceReg, index, destReg, scratchReg, needRestoreRcvr);
+	}
+	else {
+		genStoreWithImmutabilityButNoStoreCheckSourceRegslotIndexdestRegscratchRegneedRestoreRcvr(sourceReg, index, destReg, scratchReg, needRestoreRcvr);
+	}
+	return 0;
+}
+#endif /* IMMUTABILITY */
+
+
 /*	Make sure SendNumArgsReg and ClassReg are available in addition to
 	ReceiverResultReg and TempReg in
 	genGetActiveContextNumArgs:large:inBlock:. 
@@ -26242,39 +26497,22 @@
 		: falseObject()));
 }
 
-
-/*	The only reason we assert needsFrame here is that in a frameless method
-	ReceiverResultReg must and does contain only self, but the ceStoreCheck
-	trampoline expects the target of the store to be in ReceiverResultReg. So
-	in a frameless method we would have a conflict between the receiver and
-	the literal store, unless we we smart enough to realise that
-	ReceiverResultReg was unused after the literal variable store, unlikely
-	given that methods
-	return self by default. */
-
 	/* StackToRegisterMappingCogit>>#genStorePop:LiteralVariable: */
 static sqInt NoDbgRegParms
 genStorePopLiteralVariable(sqInt popBoolean, sqInt litVarIndex)
 {
-    AbstractInstruction *abstractInstruction;
-    AbstractInstruction *abstractInstruction1;
-    AbstractInstruction *abstractInstruction2;
     AbstractInstruction *anInstruction;
     AbstractInstruction *anInstruction1;
     sqInt association;
-    AbstractInstruction *fail;
-    AbstractInstruction * immutabilityFailure;
-    AbstractInstruction *mutableJump;
+    sqInt association1;
     sqInt needStoreCheck;
+    sqInt needStoreCheck1;
     sqInt topReg;
 
-	assert(needsFrame);
 	
 #  if IMMUTABILITY
-	ssFlushTo(simStackPtr - 1);
-
-#  endif /* IMMUTABILITY */
-
+	/* begin genImmutabilityCheckStorePop:LiteralVariable: */
+	assert(needsFrame);
 	needStoreCheck = !(isUnannotatableConstant(ssTop()));
 	association = getLiteral(litVarIndex);
 	(optStatus.isReceiverResultRegLive = 0);
@@ -26288,52 +26526,35 @@
 		anInstruction = genoperandoperand(MoveCqR, association, ReceiverResultReg);
 	}
 	genEnsureObjInRegNotForwardedscratchReg(ReceiverResultReg, TempReg);
-	
-#  if IMMUTABILITY
 	ssAllocateRequiredReg(ClassReg);
-	topReg = ClassReg;
 	ssStoreAndReplacePoptoReg(popBoolean, ClassReg);
 	ssFlushTo(simStackPtr);
-	/* begin genImmutableCheck:slotIndex:sourceReg:scratchReg:needRestoreRcvr: */
-	assert(ReceiverResultReg == ReceiverResultReg);
-	assert(TempReg == TempReg);
-	assert(ClassReg == ClassReg);
+	genStoreWithImmutabilityCheckSourceRegslotIndexdestRegscratchRegneedsStoreCheckneedRestoreRcvr(ClassReg, ValueIndex, ReceiverResultReg, TempReg, needStoreCheck, 0);
+	return 0;
 
-	/* We reach this code if the object mutated is immutable. */
-	mutableJump = genJumpMutablescratchReg(ReceiverResultReg, TempReg);
-	/* begin MoveCq:R: */
-	anInstruction1 = genoperandoperand(MoveCqR, ValueIndex, TempReg);
-	/* begin CallRT: */
-	abstractInstruction1 = genoperand(Call, ceCannotAssignToWithIndexTrampoline);
-	(abstractInstruction1->annotation = IsRelativeCall);
-	/* begin annotateBytecode: */
-	abstractInstruction2 = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
-	(abstractInstruction2->annotation = HasBytecodePC);
-	/* begin Jump: */
-	fail = genoperand(Jump, ((sqInt)0));
-	jmpTarget(mutableJump, gLabel());
-	immutabilityFailure = fail;
-
 #  else /* IMMUTABILITY */
+	/* begin genVanillaStorePop:LiteralVariable: */
+	assert(needsFrame);
+	needStoreCheck1 = !(isUnannotatableConstant(ssTop()));
+	association1 = getLiteral(litVarIndex);
+	(optStatus.isReceiverResultRegLive = 0);
+	ssAllocateRequiredReg(ReceiverResultReg);
+	/* begin genMoveConstant:R: */
+	if (shouldAnnotateObjectReference(association1)) {
+		annotateobjRef(gMoveCwR(association1, ReceiverResultReg), association1);
+	}
+	else {
+		/* begin MoveCq:R: */
+		anInstruction1 = genoperandoperand(MoveCqR, association1, ReceiverResultReg);
+	}
+	genEnsureObjInRegNotForwardedscratchReg(ReceiverResultReg, TempReg);
 	topReg = allocateRegForStackEntryAtnotConflictingWith(0, 1LL << ReceiverResultReg);
 	ssStorePoptoReg(popBoolean, topReg);
+	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(topReg, ValueIndex, ReceiverResultReg, TempReg, needsFrame, needStoreCheck1);
+	return 0;
 
 #  endif /* IMMUTABILITY */
 
-	if (traceStores > 0) {
-		/* begin MoveR:R: */
-		genoperandoperand(MoveRR, topReg, TempReg);
-		/* begin CallRT: */
-		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
-		(abstractInstruction->annotation = IsRelativeCall);
-	}
-	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(topReg, ValueIndex, ReceiverResultReg, TempReg, needsFrame, needStoreCheck);
-	
-#  if IMMUTABILITY
-	jmpTarget(immutabilityFailure, gLabel());
-
-#  endif /* IMMUTABILITY */
-
 	return 0;
 }
 
@@ -26343,30 +26564,20 @@
 {
     AbstractInstruction *abstractInstruction;
     AbstractInstruction *abstractInstruction1;
-    AbstractInstruction *abstractInstruction11;
-    AbstractInstruction *abstractInstruction2;
     AbstractInstruction *anInstruction;
     AbstractInstruction *anInstruction1;
-    AbstractInstruction *fail;
-    AbstractInstruction * immutabilityFailure;
     AbstractInstruction *jmpDone;
+    AbstractInstruction *jmpDone1;
     AbstractInstruction *jmpSingle;
-    AbstractInstruction *mutableJump;
+    AbstractInstruction *jmpSingle1;
     sqInt needStoreCheck;
+    sqInt needStoreCheck1;
 
-
-	/* The reason we need a frame here is that assigning to an inst var of a context may
-	   involve wholesale reorganization of stack pages, and the only way to preserve the
-	   execution state of an activation in that case is if it has a frame. */
-	assert(needsFrame);
 	
 #  if IMMUTABILITY
-	ssFlushTo(simStackPtr - 1);
+	/* begin genImmutabilityCheckStorePop:MaybeContextReceiverVariable: */
+	assert(needsFrame);
 
-#  endif /* IMMUTABILITY */
-
-	ssFlushUpThroughReceiverVariable(slotIndex);
-
 	/* Note that ReceiverResultReg remains live after both
 	   ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline. */
 	needStoreCheck = !(isUnannotatableConstant(ssTop()));
@@ -26375,68 +26586,52 @@
 	ssAllocateCallRegand(ClassReg, SendNumArgsReg);
 	ssPush(1);
 	genLoadSlotsourceRegdestReg(SenderIndex, ReceiverResultReg, TempReg);
-	
-#  if IMMUTABILITY
 	ssStoreAndReplacePoptoReg(popBoolean, ClassReg);
 	ssFlushTo(simStackPtr);
-
-#  else /* IMMUTABILITY */
-	ssStorePoptoReg(popBoolean, ClassReg);
-
-#  endif /* IMMUTABILITY */
-
 	/* begin genJumpNotSmallIntegerInScratchReg: */
 	jmpSingle = genJumpNotSmallInteger(TempReg);
 	/* begin MoveCq:R: */
 	anInstruction = genoperandoperand(MoveCqR, slotIndex, SendNumArgsReg);
 	/* begin CallRT: */
-	abstractInstruction1 = genoperand(Call, ceStoreContextInstVarTrampoline);
-	(abstractInstruction1->annotation = IsRelativeCall);
+	abstractInstruction = genoperand(Call, ceStoreContextInstVarTrampoline);
+	(abstractInstruction->annotation = IsRelativeCall);
 	/* begin Jump: */
 	jmpDone = genoperand(Jump, ((sqInt)0));
 	jmpTarget(jmpSingle, gLabel());
-	if (traceStores > 0) {
-		/* begin MoveR:R: */
-		genoperandoperand(MoveRR, ClassReg, TempReg);
-		/* begin CallRT: */
-		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
-		(abstractInstruction->annotation = IsRelativeCall);
-	}
-	
-#  if IMMUTABILITY
-	/* begin genImmutableCheck:slotIndex:sourceReg:scratchReg:needRestoreRcvr: */
-	assert(ReceiverResultReg == ReceiverResultReg);
-	assert(TempReg == TempReg);
-	assert(ClassReg == ClassReg);
+	genStoreWithImmutabilityCheckSourceRegslotIndexdestRegscratchRegneedsStoreCheckneedRestoreRcvr(ClassReg, slotIndex, ReceiverResultReg, TempReg, needStoreCheck, 1);
+	jmpTarget(jmpDone, gLabel());
+	return 0;
 
-	/* We reach this code if the object mutated is immutable. */
-	mutableJump = genJumpMutablescratchReg(ReceiverResultReg, TempReg);
+#  else /* IMMUTABILITY */
+	/* begin genVanillaStorePop:MaybeContextReceiverVariable: */
+	assert(needsFrame);
+	ssFlushUpThroughReceiverVariable(slotIndex);
+
+	/* Note that ReceiverResultReg remains live after both
+	   ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline. */
+	needStoreCheck1 = !(isUnannotatableConstant(ssTop()));
+	ensureReceiverResultRegContainsSelf();
+	ssPop(1);
+	ssAllocateCallRegand(ClassReg, SendNumArgsReg);
+	ssPush(1);
+	genLoadSlotsourceRegdestReg(SenderIndex, ReceiverResultReg, TempReg);
+	ssStorePoptoReg(popBoolean, ClassReg);
+	/* begin genJumpNotSmallIntegerInScratchReg: */
+	jmpSingle1 = genJumpNotSmallInteger(TempReg);
 	/* begin MoveCq:R: */
-	anInstruction1 = genoperandoperand(MoveCqR, ValueIndex, TempReg);
+	anInstruction1 = genoperandoperand(MoveCqR, slotIndex, SendNumArgsReg);
 	/* begin CallRT: */
-	abstractInstruction11 = genoperand(Call, ceCannotAssignToWithIndexTrampoline);
-	(abstractInstruction11->annotation = IsRelativeCall);
-	/* begin annotateBytecode: */
-	abstractInstruction2 = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
-	(abstractInstruction2->annotation = HasBytecodePC);
-	/* begin putSelfInReceiverResultReg */
-	storeToReg((&simSelf), ReceiverResultReg);
-
+	abstractInstruction1 = genoperand(Call, ceStoreContextInstVarTrampoline);
+	(abstractInstruction1->annotation = IsRelativeCall);
 	/* begin Jump: */
-	fail = genoperand(Jump, ((sqInt)0));
-	jmpTarget(mutableJump, gLabel());
-	immutabilityFailure = fail;
+	jmpDone1 = genoperand(Jump, ((sqInt)0));
+	jmpTarget(jmpSingle1, gLabel());
+	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(ClassReg, slotIndex, ReceiverResultReg, TempReg, 1, needStoreCheck1);
+	jmpTarget(jmpDone1, gLabel());
+	return 0;
 
 #  endif /* IMMUTABILITY */
 
-	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(ClassReg, slotIndex, ReceiverResultReg, TempReg, 1, needStoreCheck);
-	jmpTarget(jmpDone, gLabel());
-	
-#  if IMMUTABILITY
-	jmpTarget(immutabilityFailure, gLabel());
-
-#  endif /* IMMUTABILITY */
-
 	return 0;
 }
 
@@ -26444,89 +26639,38 @@
 static sqInt NoDbgRegParms
 genStorePopReceiverVariable(sqInt popBoolean, sqInt slotIndex)
 {
-    AbstractInstruction *abstractInstruction;
-    AbstractInstruction *abstractInstruction1;
-    AbstractInstruction *abstractInstruction11;
-    AbstractInstruction *abstractInstruction2;
-    AbstractInstruction *anInstruction;
-    AbstractInstruction *fail;
-    AbstractInstruction * immutabilityFailure;
-    AbstractInstruction *mutableJump;
     sqInt needStoreCheck;
+    sqInt needStoreCheck1;
     sqInt topReg;
 
 	
 #  if IMMUTABILITY
+	/* begin genImmutabilityCheckStorePop:ReceiverVariable: */
 	assert(needsFrame);
-	ssFlushTo(simStackPtr - 1);
 
-#  endif /* IMMUTABILITY */
-
-	ssFlushUpThroughReceiverVariable(slotIndex);
-
-	/* Note that ReceiverResultReg remains live after ceStoreCheckTrampoline. */
+	/* Note that ReceiverResultReg remains live after the trampoline. */
 	needStoreCheck = !(isUnannotatableConstant(ssTop()));
 	ensureReceiverResultRegContainsSelf();
-	
-#  if IMMUTABILITY
 	ssAllocateRequiredReg(ClassReg);
-	topReg = ClassReg;
 	ssStoreAndReplacePoptoReg(popBoolean, ClassReg);
 	ssFlushTo(simStackPtr);
-	/* begin genImmutableCheck:slotIndex:sourceReg:scratchReg:needRestoreRcvr: */
-	assert(ReceiverResultReg == ReceiverResultReg);
-	assert(TempReg == TempReg);
-	assert(ClassReg == ClassReg);
+	genStoreWithImmutabilityCheckSourceRegslotIndexdestRegscratchRegneedsStoreCheckneedRestoreRcvr(ClassReg, slotIndex, ReceiverResultReg, TempReg, needStoreCheck, 1);
+	return 0;
 
-	/* We reach this code if the object mutated is immutable. */
-	mutableJump = genJumpMutablescratchReg(ReceiverResultReg, TempReg);
-	/* begin MoveCq:R: */
-	anInstruction = genoperandoperand(MoveCqR, slotIndex, TempReg);
-	/* begin CallRT: */
-	abstractInstruction11 = genoperand(Call, ceCannotAssignToWithIndexTrampoline);
-	(abstractInstruction11->annotation = IsRelativeCall);
-	/* begin annotateBytecode: */
-	abstractInstruction2 = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
-	(abstractInstruction2->annotation = HasBytecodePC);
-	/* begin putSelfInReceiverResultReg */
-	storeToReg((&simSelf), ReceiverResultReg);
+#  else /* IMMUTABILITY */
+	/* begin genVanillaStorePop:ReceiverVariable: */
+	ssFlushUpThroughReceiverVariable(slotIndex);
 
-	/* begin Jump: */
-	fail = genoperand(Jump, ((sqInt)0));
-	jmpTarget(mutableJump, gLabel());
-	immutabilityFailure = fail;
-
-#  else /* IMMUTABILITY */
+	/* Note that ReceiverResultReg remains live after ceStoreCheckTrampoline. */
+	needStoreCheck1 = !(isUnannotatableConstant(ssTop()));
+	ensureReceiverResultRegContainsSelf();
 	topReg = allocateRegForStackEntryAtnotConflictingWith(0, 1LL << ReceiverResultReg);
 	ssStorePoptoReg(popBoolean, topReg);
+	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(topReg, slotIndex, ReceiverResultReg, TempReg, needsFrame, needStoreCheck1);
+	return 0;
 
 #  endif /* IMMUTABILITY */
 
-	if (traceStores > 0) {
-		/* begin MoveR:R: */
-		genoperandoperand(MoveRR, topReg, TempReg);
-		/* begin evaluateTrampolineCallBlock:protectLinkRegIfNot: */
-		if (needsFrame) {
-			/* begin CallRT: */
-			abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
-			(abstractInstruction->annotation = IsRelativeCall);
-
-		}
-		else {
-			/* begin CallRT: */
-			abstractInstruction1 = genoperand(Call, ceTraceStoreTrampoline);
-			(abstractInstruction1->annotation = IsRelativeCall);
-
-
-		}
-	}
-	genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(topReg, slotIndex, ReceiverResultReg, TempReg, needsFrame, needStoreCheck);
-	
-#  if IMMUTABILITY
-	jmpTarget(immutabilityFailure, gLabel());
-
-#  endif /* IMMUTABILITY */
-
 	return 0;
 }
 
@@ -26543,7 +26687,6 @@
 static sqInt NoDbgRegParms
 genStorePopRemoteTempAt(sqInt popBoolean, sqInt slotIndex, sqInt remoteTempIndex)
 {
-    AbstractInstruction *abstractInstruction;
     AbstractInstruction *anInstruction;
     sqInt needStoreCheck;
     sqInt offset;
@@ -26559,13 +26702,6 @@
 	offset = frameOffsetOfTemporary(remoteTempIndex);
 	/* begin gen:quickConstant:operand:operand: */
 	anInstruction = genoperandoperandoperand(MoveMwrR, offset, FPReg, ReceiverResultReg);
-	if (traceStores > 0) {
-		/* begin MoveR:R: */
-		genoperandoperand(MoveRR, topReg, TempReg);
-		/* begin CallRT: */
-		abstractInstruction = genoperand(Call, ceTraceStoreTrampoline);
-		(abstractInstruction->annotation = IsRelativeCall);
-	}
 	return genStoreSourceRegslotIndexdestRegscratchReginFrameneedsStoreCheck(topReg, slotIndex, ReceiverResultReg, TempReg, needsFrame, needStoreCheck);
 }
 

Modified: branches/Cog/nsspur64src/vm/cointerp.c
===================================================================
--- branches/Cog/nsspur64src/vm/cointerp.c	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/nsspur64src/vm/cointerp.c	2016-04-01 00:36:10 UTC (rev 3666)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
    from
-	CoInterpreter VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CoInterpreter VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -2441,7 +2441,7 @@
 /*560*/	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0,-1,-1
 	};
 char expensiveAsserts = 0;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1746";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1756";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -40996,6 +40996,10 @@
 	result = 0;
 l8:	/* end stObject:at: */;
 	if (!GIV(primFailCode)) {
+		if (!(((result >= 0) && (result <= ((1LL << 30) - 1))))) {
+			GIV(primFailCode) = PrimErrBadReceiver;
+			goto l2;
+		}
 		result = (((long)((result >> 3))) << (numTagBits())) + (characterTag());
 
 
@@ -67205,7 +67209,7 @@
 bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil)
 {
     usqInt bridgeSpan;
-    sqInt clifton;
+    usqInt clifton;
     usqInt segEnd;
 
 	segEnd = ((aSegment->segSize)) + ((aSegment->segStart));
@@ -67578,7 +67582,7 @@
 static sqInt NoDbgRegParms
 readHeapFromImageFiledataBytes(sqImageFile f, sqInt numBytes)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
-    usqInt bridge;
+    sqInt bridge;
     usqInt bridgehead;
     usqLong bridgeSpan;
     sqInt bytesRead;

Modified: branches/Cog/nsspur64src/vm/cointerp.h
===================================================================
--- branches/Cog/nsspur64src/vm/cointerp.h	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/nsspur64src/vm/cointerp.h	2016-04-01 00:36:10 UTC (rev 3666)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
  */
 
 

Modified: branches/Cog/nsspur64src/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nsspur64src/vm/gcc3x-cointerp.c	2016-03-30 07:32:09 UTC (rev 3665)
+++ branches/Cog/nsspur64src/vm/gcc3x-cointerp.c	2016-04-01 00:36:10 UTC (rev 3666)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
    from
-	CoInterpreter VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288
+	CoInterpreter VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1746 uuid: 9e4a49eb-8ebe-486d-b6f0-430100efa288 " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.1756 uuid: 141cf0f3-955a-486f-8082-decbc14645d7 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -2444,7 +2444,7 @@
 /*560*/	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0,-1,-1
 	};
 char expensiveAsserts = 0;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1746";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreterPrimitives_VMMaker.oscog-eem.1756";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 40 */;
 volatile int sendTrace;
 
@@ -41005,6 +41005,10 @@
 	result = 0;
 l8:	/* end stObject:at: */;
 	if (!GIV(primFailCode)) {
+		if (!(((result >= 0) && (result <= ((1LL << 30) - 1))))) {
+			GIV(primFailCode) = PrimErrBadReceiver;
+			goto l2;
+		}
 		result = (((long)((result >> 3))) << (numTagBits())) + (characterTag());
 
 
@@ -67214,7 +67218,7 @@
 bridgeFromto(SpurSegmentInfo *aSegment, SpurSegmentInfo *nextSegmentOrNil)
 {
     usqInt bridgeSpan;
-    sqInt clifton;

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list