[Vm-dev] [commit][3404] CogVM source as per VMMaker.oscog-eem.1423

commits at squeakvm.org commits at squeakvm.org
Thu Jul 16 15:25:59 UTC 2015


Revision: 3404
Author:   eliot
Date:     2015-07-16 08:25:58 -0700 (Thu, 16 Jul 2015)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.1423

All Cogits:
Implement a machine code perform:[with:]* primitive.  Eliminate the duplication
of SimpleStackBasedCogit/StackToRegisterMappingCogit>>compileOpenPIC:numArgs:
now that we have dead code elimination enabled.

ARM Cogits:
Use __aeabit_idivmod to implement machine code div/mod primitives on ARM.

64-bits:
Change the type of the event buffer from int[8] to long[8].

Newspeak:
Compile Newspeak self and super sends as clean sends as well.
Slower in monomorphic case but net win for the larger benchmarks, presumably
because it avoids I-cache flushes in the polymorphic case.

Also means implementing polymorphic caches for clean sends will benefit all
non-ordinary sends.

	DeltaBlue +8.2%
	Splay +7.6%
	ParserCombinators +4.7%
	Richards +0.5%
	SlotRead (replaced with self send) -17.6%

Spill ReceiverResultReg before runtime call to fix pushEnclosingObject on ARM.
(ReceiverResultReg is edx/caller-saved on IA32 but r7/callee-saved on ARM.)

Fix the 64-bit Newspeak builds' plugins.ext

Nuke obsolete newspeak.*.v3 build directories.

Modified Paths:
--------------
    branches/Cog/build.linux64x64/newspeak.cog.spur/plugins.ext
    branches/Cog/build.linux64x64/newspeak.sista.spur/plugins.ext
    branches/Cog/build.linux64x64/newspeak.stack.spur/plugins.ext
    branches/Cog/nsspursrc/vm/cogit.h
    branches/Cog/nsspursrc/vm/cogitARMv5.c
    branches/Cog/nsspursrc/vm/cogitIA32.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/config/bin.squeak.sh.in
    branches/Cog/platforms/unix/config/squeak.sh.in
    branches/Cog/spursistasrc/vm/cogit.h
    branches/Cog/spursistasrc/vm/cogitARMv5.c
    branches/Cog/spursistasrc/vm/cogitIA32.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/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/vm/cogit.h
    branches/Cog/src/vm/cogitARMv5.c
    branches/Cog/src/vm/cogitIA32.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

Removed Paths:
-------------
    branches/Cog/build.linux32x86/newspeak.cog.v3/build/
    branches/Cog/build.linux32x86/newspeak.cog.v3/build.assert/
    branches/Cog/build.linux32x86/newspeak.cog.v3/build.assert.itimerheartbeat/
    branches/Cog/build.linux32x86/newspeak.cog.v3/build.debug/
    branches/Cog/build.linux32x86/newspeak.cog.v3/build.debug.itimerheartbeat/
    branches/Cog/build.linux32x86/newspeak.cog.v3/build.itimerheartbeat/
    branches/Cog/build.linux32x86/newspeak.cog.v3/makeallclean
    branches/Cog/build.linux32x86/newspeak.cog.v3/makealldirty
    branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.ext
    branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.int
    branches/Cog/build.win32x86/newspeak.cog.v3/

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

Deleted: branches/Cog/build.linux32x86/newspeak.cog.v3/makeallclean
===================================================================
--- branches/Cog/build.linux32x86/newspeak.cog.v3/makeallclean	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux32x86/newspeak.cog.v3/makeallclean	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,6 +0,0 @@
-#!/bin/sh
-trap 'exit 2' HUP INT PIPE TERM
-for d in `dirname $0`/build*; do
-	(cd $d
-	 echo y | ./mvm "$@")
-done

Deleted: branches/Cog/build.linux32x86/newspeak.cog.v3/makealldirty
===================================================================
--- branches/Cog/build.linux32x86/newspeak.cog.v3/makealldirty	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux32x86/newspeak.cog.v3/makealldirty	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,6 +0,0 @@
-#!/bin/sh
-trap 'exit 2' HUP INT PIPE TERM
-for d in `dirname $0`/build*; do
-	(cd $d
-	 echo n | ./mvm "$@")
-done

Deleted: branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.ext
===================================================================
--- branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.ext	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.ext	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,3 +0,0 @@
-# Copied, perhaps edited, from ../../../nscogsrc/examplePlugins.ext
-EXTERNAL_PLUGINS = \
-SqueakSSL

Deleted: branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.int
===================================================================
--- branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.int	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux32x86/newspeak.cog.v3/plugins.int	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,27 +0,0 @@
-# Copied, perhaps edited, from ../../../nscogsrc/examplePlugins.int
-INTERNAL_PLUGINS = \
-AioPlugin \
-AsynchFilePlugin \
-BMPReadWriterPlugin \
-B2DPlugin \
-BitBltPlugin \
-DSAPrims \
-DropPlugin \
-FileCopyPlugin \
-FilePlugin \
-FloatArrayPlugin \
-FloatMathPlugin \
-ZipPlugin \
-JPEGReadWriter2Plugin \
-JPEGReaderPlugin \
-LargeIntegers \
-Matrix2x3Plugin \
-MiscPrimitivePlugin \
-IA32ABI \
-RePlugin \
-SecurityPlugin \
-SocketPlugin \
-SurfacePlugin \
-UUIDPlugin \
-UnixOSProcessPlugin \
-VMProfileLinuxSupportPlugin

Modified: branches/Cog/build.linux64x64/newspeak.cog.spur/plugins.ext
===================================================================
--- branches/Cog/build.linux64x64/newspeak.cog.spur/plugins.ext	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux64x64/newspeak.cog.spur/plugins.ext	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,10 +1,3 @@
-# Copied, perhaps edited, from ../../src/examplePlugins.ext
-# SqueakFFIPrims needs implementing
-EXTERNAL_PLUGINS = \
-B3DAcceleratorPlugin \
-SqueakSSL \
-LocalePlugin \
-UnicodePlugin \
-UnixOSProcessPlugin \
-UUIDPlugin \
-XDisplayControlPlugin
+# Copied, perhaps edited, from ../../../nscogsrc/examplePlugins.ext
+EXTERNAL_PLUGINS = \
+SqueakSSL

Modified: branches/Cog/build.linux64x64/newspeak.sista.spur/plugins.ext
===================================================================
--- branches/Cog/build.linux64x64/newspeak.sista.spur/plugins.ext	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux64x64/newspeak.sista.spur/plugins.ext	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,10 +1,3 @@
-# Copied, perhaps edited, from ../../src/examplePlugins.ext
-# SqueakFFIPrims needs implementing
-EXTERNAL_PLUGINS = \
-B3DAcceleratorPlugin \
-SqueakSSL \
-LocalePlugin \
-UnicodePlugin \
-UnixOSProcessPlugin \
-UUIDPlugin \
-XDisplayControlPlugin
+# Copied, perhaps edited, from ../../../nscogsrc/examplePlugins.ext
+EXTERNAL_PLUGINS = \
+SqueakSSL

Modified: branches/Cog/build.linux64x64/newspeak.stack.spur/plugins.ext
===================================================================
--- branches/Cog/build.linux64x64/newspeak.stack.spur/plugins.ext	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/build.linux64x64/newspeak.stack.spur/plugins.ext	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,10 +1,3 @@
-# Copied, perhaps edited, from ../../src/examplePlugins.ext
-# SqueakFFIPrims needs implementing
-EXTERNAL_PLUGINS = \
-B3DAcceleratorPlugin \
-SqueakSSL \
-LocalePlugin \
-UnicodePlugin \
-UnixOSProcessPlugin \
-UUIDPlugin \
-XDisplayControlPlugin
+# Copied, perhaps edited, from ../../../nscogsrc/examplePlugins.ext
+EXTERNAL_PLUGINS = \
+SqueakSSL

Modified: branches/Cog/nsspursrc/vm/cogit.h
===================================================================
--- branches/Cog/nsspursrc/vm/cogit.h	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/nsspursrc/vm/cogit.h	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b
+	CCodeGenerator VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe
  */
 
 

Modified: branches/Cog/nsspursrc/vm/cogitARMv5.c
===================================================================
--- branches/Cog/nsspursrc/vm/cogitARMv5.c	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/nsspursrc/vm/cogitARMv5.c	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b
+	CCodeGenerator VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b
+	StackToRegisterMappingCogit VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -952,6 +952,7 @@
 static sqInt compileFallbackToInterpreterPrimitive(void);
 static void compileGetErrorCode(void);
 static sqInt compileInterpreterPrimitive(void (*primitiveRoutine)(void)) NoDbgRegParms;
+static void compileOpenPICnumArgs(sqInt selector, sqInt numArgs) NoDbgRegParms;
 static sqInt extendedPushBytecode(void);
 static sqInt extendedStoreAndPopBytecode(void);
 static sqInt extendedStoreBytecode(void);
@@ -989,6 +990,7 @@
 static sqInt genLongStoreTemporaryVariableBytecode(void);
 static sqInt genLongUnconditionalBackwardJump(void);
 static sqInt genLongUnconditionalForwardJump(void);
+static sqInt genLookupForPerformNumArgs(sqInt numArgs) NoDbgRegParms;
 static AbstractInstruction * genMoveFalseR(sqInt reg) NoDbgRegParms;
 static AbstractInstruction * genMoveTrueR(sqInt reg) NoDbgRegParms;
 static sqInt genMustBeBooleanTrampolineForcalled(sqInt boolean, char *trampolineName) NoDbgRegParms;
@@ -1059,6 +1061,7 @@
 static sqInt v4LongBranchDistance(BytecodeDescriptor *descriptor, sqInt pc, sqInt nExts, sqInt aMethodObj) NoDbgRegParms;
 extern void voidCogCompiledCode(void);
 static BlockStart * addBlockStartAtnumArgsnumCopiedspan(sqInt bytecodepc, sqInt numArgs, sqInt numCopied, sqInt span) NoDbgRegParms;
+static void adjustArgumentsForPerform(sqInt numArgs) NoDbgRegParms;
 static sqInt allocateRegForStackEntryAtnotConflictingWith(sqInt index, sqInt regMask) NoDbgRegParms;
 static sqInt allocateRegNotConflictingWith(sqInt regMask) NoDbgRegParms;
 static void annotateBytecodeIfAnnotated(CogSimStackEntry *aSimStackEntry) NoDbgRegParms;
@@ -1072,7 +1075,6 @@
 static CogMethod * compileCogMethod(sqInt selector) NoDbgRegParms;
 static sqInt compileEntireMethod(void);
 static sqInt compileFrameBuild(void);
-static void compileOpenPICnumArgs(sqInt selector, sqInt numArgs) NoDbgRegParms;
 static sqInt cPICMissTrampolineFor(sqInt numArgs) NoDbgRegParms;
 static sqInt doubleExtendedDoAnythingBytecode(void);
 static sqInt duplicateTopBytecode(void);
@@ -1129,6 +1131,7 @@
 static sqInt genPrimitiveNewMethod(void);
 static sqInt genPrimitiveNewWithArg(void);
 static sqInt genPrimitiveNotIdentical(void);
+static sqInt genPrimitivePerform(void);
 static sqInt genPrimitiveQuo(void);
 static sqInt genPrimitiveSize(void);
 static sqInt genPrimitiveStringAt(void);
@@ -9892,7 +9895,7 @@
 {
     sqInt classIndex;
     sqInt i;
-    usqInt pc;
+    sqInt pc;
 
 	pc = (((((usqInt)cPIC)) + firstCPICCaseOffset) + cPICCaseSize) - (jumpLongConditionalByteSize(backEnd));
 	for (i = 2; i <= ((cPIC->cPICNumCases)); i += 1) {
@@ -13704,6 +13707,7 @@
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
+	{ genPrimitivePerform, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
@@ -13730,7 +13734,6 @@
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
-	{ 0, -1, 0 },
 	{ genPrimitiveIdentical, 1, 0 },
 	{ genPrimitiveClass, -1, 0 },
 	{ 0, -1, 0 },
@@ -21106,6 +21109,125 @@
 	return 0;
 }
 
+
+/*	Compile the code for an open PIC. Perform a probe of the first-level
+	method lookup cache followed by a call of ceSendFromInLineCacheMiss: if
+	the probe fails. */
+
+	/* SimpleStackBasedCogit>>#compileOpenPIC:numArgs: */
+static void
+compileOpenPICnumArgs(sqInt selector, sqInt numArgs)
+{
+    AbstractInstruction *itsAHit;
+    AbstractInstruction *jumpBCMethod;
+    AbstractInstruction *jumpClassMiss;
+    AbstractInstruction *jumpSelectorMiss;
+    sqInt offset;
+    sqInt offset1;
+    sqInt offset2;
+    sqInt offset3;
+    sqInt offset4;
+    sqInt offset5;
+    sqInt offset6;
+
+	compilePICAbort(numArgs);
+
+	/* Do first of three probes.  See CoInterpreter>>lookupInMethodCacheSel:classTag: */
+
+	entry = genGetClassTagOfintoscratchReg(ReceiverResultReg, ClassReg, TempReg);
+	flag("lookupInMethodCacheSel:classTag:");
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, shiftForWord(), ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset, genoperandoperandoperand(MoveMwrR, offset, ClassReg, TempReg));
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset1 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset1, genoperandoperandoperand(MoveMwrR, offset1, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpNonZero: */
+	jumpClassMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin Label */
+	itsAHit = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	/* begin MoveMw:r:R: */
+	offset2 = (((usqInt)(methodCacheAddress()))) + (MethodCacheMethod << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset2, genoperandoperandoperand(MoveMwrR, offset2, ClassReg, SendNumArgsReg));
+	genLoadSlotsourceRegdestReg(HeaderIndex, SendNumArgsReg, ClassReg);
+	jumpBCMethod = genJumpImmediate(ClassReg);
+	jmpTarget(jumpBCMethod, picInterpretAbort);
+	/* begin AddCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(cmNoCheckEntryOffset, genoperandoperand(AddCqR, cmNoCheckEntryOffset, ClassReg));
+	/* begin JumpR: */
+	genoperand(JumpR, ClassReg);
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpClassMiss, gLabel()));
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, (shiftForWord()) - 1, ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset3 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset3, genoperandoperandoperand(MoveMwrR, offset3, ClassReg, TempReg));
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset4 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset4, genoperandoperandoperand(MoveMwrR, offset4, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset5 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset5, genoperandoperandoperand(MoveMwrR, offset5, ClassReg, TempReg));
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset6 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset6, genoperandoperandoperand(MoveMwrR, offset6, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	genPushRegisterArgsForNumArgsscratchReg(backEnd, numArgs, SendNumArgsReg);
+
+	genSmalltalkToCStackSwitch(1);
+	addDependent(methodLabel, annotateAbsolutePCRef(gMoveCwR(((sqInt)methodLabel), SendNumArgsReg)));
+	compileCallFornumArgsargargargargresultRegsaveRegs(ceSendFromInLineCacheMiss, 1, SendNumArgsReg, null, null, null, null, 0);
+}
+
 	/* SimpleStackBasedCogit>>#extendedPushBytecode */
 static sqInt
 extendedPushBytecode(void)
@@ -21768,6 +21890,131 @@
 	return genJumpTo(targetpc);
 }
 
+
+/*	Compile the code for a probe of the first-level method cache for a perform
+	primtiive. The selector is assumed to be in Arg0Reg. Defer to
+	adjustArgumentsForPerform: to
+	adjust the arguments before the jump to the method. */
+
+	/* SimpleStackBasedCogit>>#genLookupForPerformNumArgs: */
+static sqInt
+genLookupForPerformNumArgs(sqInt numArgs)
+{
+    AbstractInstruction *itsAHit;
+    AbstractInstruction *jumpClassMiss;
+    AbstractInstruction *jumpInterpret;
+    AbstractInstruction *jumpSelectorMiss;
+    sqInt offset;
+    sqInt offset1;
+    sqInt offset2;
+    sqInt offset3;
+    sqInt offset4;
+    sqInt offset5;
+    sqInt offset6;
+
+
+	/* N.B.  Can't assume TempReg already contains the tag because a method can
+	   of course be invoked via the unchecked entry-point, e.g. as does perform:. */
+
+	genGetInlineCacheClassTagFromintoforEntry(ReceiverResultReg, ClassReg, 0);
+	flag("lookupInMethodCacheSel:classTag:");
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, shiftForWord(), ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset, genoperandoperandoperand(MoveMwrR, offset, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset1 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset1, genoperandoperandoperand(MoveMwrR, offset1, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpNonZero: */
+	jumpClassMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin Label */
+	itsAHit = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	/* begin MoveMw:r:R: */
+	offset2 = (((usqInt)(methodCacheAddress()))) + (MethodCacheMethod << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset2, genoperandoperandoperand(MoveMwrR, offset2, ClassReg, SendNumArgsReg));
+	genLoadSlotsourceRegdestReg(HeaderIndex, SendNumArgsReg, ClassReg);
+
+	/* Adjust arguments and jump to the method's unchecked entry-point. */
+
+	jumpInterpret = genJumpImmediate(ClassReg);
+	/* begin AddCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(cmNoCheckEntryOffset, genoperandoperand(AddCqR, cmNoCheckEntryOffset, ClassReg));
+	adjustArgumentsForPerform(numArgs);
+	/* begin JumpR: */
+	genoperand(JumpR, ClassReg);
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpClassMiss, gLabel()));
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, (shiftForWord()) - 1, ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset3 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset3, genoperandoperandoperand(MoveMwrR, offset3, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset4 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset4, genoperandoperandoperand(MoveMwrR, offset4, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
+	/* begin MoveMw:r:R: */
+	offset5 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset5, genoperandoperandoperand(MoveMwrR, offset5, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset6 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	checkQuickConstantforInstruction(offset6, genoperandoperandoperand(MoveMwrR, offset6, ClassReg, TempReg));
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpInterpret, gLabel()));
+	return 0;
+}
+
 	/* SimpleStackBasedCogit>>#genMoveFalseR: */
 static AbstractInstruction *
 genMoveFalseR(sqInt reg)
@@ -22771,6 +23018,56 @@
 }
 
 
+/*	e.g.	Receiver				Receiver
+	Selector/Arg0	=>		Arg1
+	Arg1					Arg2
+	Arg2			sp->	retpc
+	sp->	retpc */
+/*	Generate code to adjust the possibly stacked arguments immediately
+	before jumping to a method looked up by a perform primitive. */
+
+	/* StackToRegisterMappingCogit>>#adjustArgumentsForPerform: */
+static void
+adjustArgumentsForPerform(sqInt numArgs)
+{
+    sqInt index;
+    sqInt offset;
+
+	assert((numRegArgs()) <= 2);
+	assert(numArgs >= 1);
+	if (numArgs <= 2) {
+		if (numArgs == 2) {
+			/* begin MoveR:R: */
+			genoperandoperand(MoveRR, Arg1Reg, Arg0Reg);
+		}
+		return;
+	}
+	if ((2 + 1) == numArgs) {
+		/* begin PopR: */
+		genoperand(PopR, Arg1Reg);
+
+		/* begin PopR: */
+		genoperand(PopR, Arg0Reg);
+
+		return;
+	}
+	for (index = (numArgs - 2); index >= 0; index += -1) {
+		/* begin MoveMw:r:R: */
+		/* begin gen:quickConstant:operand:operand: */
+		checkQuickConstantforInstruction(index * BytesPerWord, genoperandoperandoperand(MoveMwrR, index * BytesPerWord, SPReg, TempReg));
+		/* begin MoveR:Mw:r: */
+		offset = (index + 1) * BytesPerWord;
+		/* begin gen:operand:quickConstant:operand: */
+		checkQuickConstantforInstruction(offset, genoperandoperandoperand(MoveRMwr, TempReg, offset, SPReg));
+	}
+	/* begin PopR: */
+	genoperand(PopR, TempReg);
+	/* begin MoveR:Mw:r: */
+	/* begin gen:operand:quickConstant:operand: */
+	checkQuickConstantforInstruction(0, genoperandoperandoperand(MoveRMwr, TempReg, 0, SPReg));
+}
+
+
 /*	If the stack entry is already in a register not conflicting with regMask,
 	answers it,
 	else allocate a new register not conflicting with reg mask
@@ -23393,125 +23690,6 @@
 	initSimStackForFramefulMethod(initialPC);
 }
 
-
-/*	Compile the code for an open PIC. Perform a probe of the first-level
-	method lookup cache followed by a call of ceSendFromInLineCacheMiss: if
-	the probe fails.
-	Override to push the register args when calling ceSendFromInLineCacheMiss: */
-
-	/* StackToRegisterMappingCogit>>#compileOpenPIC:numArgs: */
-static void
-compileOpenPICnumArgs(sqInt selector, sqInt numArgs)
-{
-    AbstractInstruction *itsAHit;
-    AbstractInstruction *jumpBCMethod;
-    AbstractInstruction *jumpClassMiss;
-    AbstractInstruction *jumpSelectorMiss;
-    sqInt offset;
-    sqInt offset1;
-    sqInt offset2;
-    sqInt offset3;
-    sqInt offset4;
-    sqInt offset5;
-    sqInt offset6;
-
-	compilePICAbort(numArgs);
-
-	/* Do first of three probes.  See CoInterpreter>>lookupInMethodCacheSel:classTag: */
-
-	entry = genGetClassTagOfintoscratchReg(ReceiverResultReg, ClassReg, TempReg);
-	flag("lookupInMethodCacheSel:classTag:");
-	/* begin MoveR:R: */
-	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);
-	annotateobjRef(gXorCwR(selector, ClassReg), selector);
-	/* begin LogicalShiftLeftCq:R: */
-	genoperandoperand(LogicalShiftLeftCqR, shiftForWord(), ClassReg);
-	/* begin AndCq:R: */
-	/* begin gen:quickConstant:operand: */
-	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
-	/* begin MoveMw:r:R: */
-	offset = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset, genoperandoperandoperand(MoveMwrR, offset, ClassReg, TempReg));
-	annotateobjRef(gCmpCwR(selector, TempReg), selector);
-	/* begin JumpNonZero: */
-	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
-	/* begin MoveMw:r:R: */
-	offset1 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset1, genoperandoperandoperand(MoveMwrR, offset1, ClassReg, TempReg));
-	/* begin CmpR:R: */
-	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
-	/* begin JumpNonZero: */
-	jumpClassMiss = genoperand(JumpNonZero, ((sqInt)0));
-	/* begin Label */
-	itsAHit = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
-	/* begin MoveMw:r:R: */
-	offset2 = (((usqInt)(methodCacheAddress()))) + (MethodCacheMethod << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset2, genoperandoperandoperand(MoveMwrR, offset2, ClassReg, SendNumArgsReg));
-	genLoadSlotsourceRegdestReg(HeaderIndex, SendNumArgsReg, ClassReg);
-	jumpBCMethod = genJumpImmediate(ClassReg);
-	jmpTarget(jumpBCMethod, picInterpretAbort);
-	/* begin AddCq:R: */
-	/* begin gen:quickConstant:operand: */
-	checkQuickConstantforInstruction(cmNoCheckEntryOffset, genoperandoperand(AddCqR, cmNoCheckEntryOffset, ClassReg));
-	/* begin JumpR: */
-	genoperand(JumpR, ClassReg);
-	jmpTarget(jumpSelectorMiss, jmpTarget(jumpClassMiss, gLabel()));
-	/* begin MoveR:R: */
-	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
-	annotateobjRef(gXorCwR(selector, ClassReg), selector);
-	/* begin LogicalShiftLeftCq:R: */
-	genoperandoperand(LogicalShiftLeftCqR, (shiftForWord()) - 1, ClassReg);
-	/* begin AndCq:R: */
-	/* begin gen:quickConstant:operand: */
-	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
-	/* begin MoveMw:r:R: */
-	offset3 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset3, genoperandoperandoperand(MoveMwrR, offset3, ClassReg, TempReg));
-	annotateobjRef(gCmpCwR(selector, TempReg), selector);
-	/* begin JumpNonZero: */
-	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
-	/* begin MoveMw:r:R: */
-	offset4 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset4, genoperandoperandoperand(MoveMwrR, offset4, ClassReg, TempReg));
-	/* begin CmpR:R: */
-	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
-	/* begin JumpZero: */
-	genoperand(JumpZero, ((sqInt)itsAHit));
-	jmpTarget(jumpSelectorMiss, gLabel());
-	/* begin MoveR:R: */
-	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
-	annotateobjRef(gXorCwR(selector, ClassReg), selector);
-	
-	/* begin AndCq:R: */
-	/* begin gen:quickConstant:operand: */
-	checkQuickConstantforInstruction(MethodCacheMask << (shiftForWord()), genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg));
-	/* begin MoveMw:r:R: */
-	offset5 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset5, genoperandoperandoperand(MoveMwrR, offset5, ClassReg, TempReg));
-	annotateobjRef(gCmpCwR(selector, TempReg), selector);
-	/* begin JumpNonZero: */
-	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
-	/* begin MoveMw:r:R: */
-	offset6 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
-	/* begin gen:quickConstant:operand:operand: */
-	checkQuickConstantforInstruction(offset6, genoperandoperandoperand(MoveMwrR, offset6, ClassReg, TempReg));
-	/* begin CmpR:R: */
-	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
-	/* begin JumpZero: */
-	genoperand(JumpZero, ((sqInt)itsAHit));
-	jmpTarget(jumpSelectorMiss, gLabel());
-	genPushRegisterArgsForNumArgsscratchReg(backEnd, numArgs, SendNumArgsReg);
-	genSmalltalkToCStackSwitch(1);
-	addDependent(methodLabel, annotateAbsolutePCRef(gMoveCwR(((sqInt)methodLabel), SendNumArgsReg)));
-	compileCallFornumArgsargargargargresultRegsaveRegs(ceSendFromInLineCacheMiss, 1, SendNumArgsReg, null, null, null, null, 0);
-}
-
 	/* StackToRegisterMappingCogit>>#cPICMissTrampolineFor: */
 static sqInt
 cPICMissTrampolineFor(sqInt numArgs)
@@ -25667,6 +25845,28 @@
 	return genInnerPrimitiveIdenticalorNotIf(0, 1);
 }
 
+
+/*	Generate an in-line perform primitive. The lookup code requires the
+	selector to be in Arg0Reg.
+	adjustArgumentsForPerform: adjusts the arguments once
+	genLookupForPerformNumArgs: has generated the code for the lookup. */
+
+	/* StackToRegisterMappingCogit>>#genPrimitivePerform */
+static sqInt
+genPrimitivePerform(void)
+{
+    sqInt offset;
+
+	if (methodOrBlockNumArgs > 2) {
+		/* begin MoveMw:r:R: */
+		offset = (methodOrBlockNumArgs - 1) * BytesPerWord;
+		/* begin gen:quickConstant:operand:operand: */
+		checkQuickConstantforInstruction(offset, genoperandoperandoperand(MoveMwrR, offset, SPReg, Arg0Reg));
+	}
+	genLookupForPerformNumArgs(methodOrBlockNumArgs);
+	return compileInterpreterPrimitive(functionPointerForCompiledMethodprimitiveIndex(methodObj, primitiveIndex));
+}
+
 	/* StackToRegisterMappingCogit>>#genPrimitiveQuo */
 static sqInt
 genPrimitiveQuo(void)

Modified: branches/Cog/nsspursrc/vm/cogitIA32.c
===================================================================
--- branches/Cog/nsspursrc/vm/cogitIA32.c	2015-07-14 22:46:03 UTC (rev 3403)
+++ branches/Cog/nsspursrc/vm/cogitIA32.c	2015-07-16 15:25:58 UTC (rev 3404)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b
+	CCodeGenerator VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b
+	StackToRegisterMappingCogit VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1417 uuid: 5220753e-35a2-46e9-89ad-f7e65d93073b " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.1423 uuid: cf39cfd3-52f5-4f6b-bba6-892ee83000fe " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -871,6 +871,7 @@
 static sqInt compileFallbackToInterpreterPrimitive(void);
 static void compileGetErrorCode(void);
 static sqInt compileInterpreterPrimitive(void (*primitiveRoutine)(void)) NoDbgRegParms;
+static void compileOpenPICnumArgs(sqInt selector, sqInt numArgs) NoDbgRegParms;
 static sqInt extendedPushBytecode(void);
 static sqInt extendedStoreAndPopBytecode(void);
 static sqInt extendedStoreBytecode(void);
@@ -908,6 +909,7 @@
 static sqInt genLongStoreTemporaryVariableBytecode(void);
 static sqInt genLongUnconditionalBackwardJump(void);
 static sqInt genLongUnconditionalForwardJump(void);
+static sqInt genLookupForPerformNumArgs(sqInt numArgs) NoDbgRegParms;
 static AbstractInstruction * genMoveFalseR(sqInt reg) NoDbgRegParms;
 static AbstractInstruction * genMoveTrueR(sqInt reg) NoDbgRegParms;
 static sqInt genMustBeBooleanTrampolineForcalled(sqInt boolean, char *trampolineName) NoDbgRegParms;
@@ -978,6 +980,7 @@
 static sqInt v4LongBranchDistance(BytecodeDescriptor *descriptor, sqInt pc, sqInt nExts, sqInt aMethodObj) NoDbgRegParms;
 extern void voidCogCompiledCode(void);
 static BlockStart * addBlockStartAtnumArgsnumCopiedspan(sqInt bytecodepc, sqInt numArgs, sqInt numCopied, sqInt span) NoDbgRegParms;
+static void adjustArgumentsForPerform(sqInt numArgs) NoDbgRegParms;
 static sqInt allocateRegForStackEntryAtnotConflictingWith(sqInt index, sqInt regMask) NoDbgRegParms;
 static sqInt allocateRegNotConflictingWith(sqInt regMask) NoDbgRegParms;
 static void annotateBytecodeIfAnnotated(CogSimStackEntry *aSimStackEntry) NoDbgRegParms;
@@ -991,7 +994,6 @@
 static CogMethod * compileCogMethod(sqInt selector) NoDbgRegParms;
 static sqInt compileEntireMethod(void);
 static sqInt compileFrameBuild(void);
-static void compileOpenPICnumArgs(sqInt selector, sqInt numArgs) NoDbgRegParms;
 static sqInt cPICMissTrampolineFor(sqInt numArgs) NoDbgRegParms;
 static sqInt doubleExtendedDoAnythingBytecode(void);
 static sqInt duplicateTopBytecode(void);
@@ -1048,6 +1050,7 @@
 static sqInt genPrimitiveNewMethod(void);
 static sqInt genPrimitiveNewWithArg(void);
 static sqInt genPrimitiveNotIdentical(void);
+static sqInt genPrimitivePerform(void);
 static sqInt genPrimitiveQuo(void);
 static sqInt genPrimitiveSize(void);
 static sqInt genPrimitiveStringAt(void);
@@ -9990,12 +9993,12 @@
 generateMapAtstart(sqInt addressOrNull, sqInt startAddress)
 {
     unsigned char annotation;
-    sqInt delta;
+    usqInt delta;
     sqInt i;
     AbstractInstruction *instruction;
     sqInt length;
-    sqInt location;
-    sqInt mapEntry;
+    usqInt location;
+    usqInt mapEntry;
     sqInt maxDelta;
     usqInt mcpc;
 
@@ -12843,6 +12846,7 @@
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
+	{ genPrimitivePerform, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
@@ -12869,7 +12873,6 @@
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
 	{ 0, -1, 0 },
-	{ 0, -1, 0 },
 	{ genPrimitiveIdentical, 1, 0 },
 	{ genPrimitiveClass, -1, 0 },
 	{ 0, -1, 0 },
@@ -20435,6 +20438,164 @@
 	return 0;
 }
 
+
+/*	Compile the code for an open PIC. Perform a probe of the first-level
+	method lookup cache followed by a call of ceSendFromInLineCacheMiss: if
+	the probe fails. */
+
+	/* SimpleStackBasedCogit>>#compileOpenPIC:numArgs: */
+static void
+compileOpenPICnumArgs(sqInt selector, sqInt numArgs)
+{
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    AbstractInstruction *anInstruction10;
+    AbstractInstruction *anInstruction2;
+    AbstractInstruction *anInstruction3;
+    AbstractInstruction *anInstruction4;
+    AbstractInstruction *anInstruction5;
+    AbstractInstruction *anInstruction6;
+    AbstractInstruction *anInstruction7;
+    AbstractInstruction *anInstruction8;
+    AbstractInstruction *anInstruction9;
+    AbstractInstruction *itsAHit;
+    AbstractInstruction *jumpBCMethod;
+    AbstractInstruction *jumpClassMiss;
+    AbstractInstruction *jumpSelectorMiss;
+    sqInt literal;
+    sqInt literal1;
+    sqInt literal2;
+    sqInt offset;
+    sqInt offset1;
+    sqInt offset2;
+    sqInt offset3;
+    sqInt offset4;
+    sqInt offset5;
+    sqInt offset6;
+
+	compilePICAbort(numArgs);
+
+	/* Do first of three probes.  See CoInterpreter>>lookupInMethodCacheSel:classTag: */
+
+	entry = genGetClassTagOfintoscratchReg(ReceiverResultReg, ClassReg, TempReg);
+	flag("lookupInMethodCacheSel:classTag:");
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, shiftForWord(), ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	literal = MethodCacheMask << (shiftForWord());
+	anInstruction = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction;
+	/* begin MoveMw:r:R: */
+	offset = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction1 = genoperandoperandoperand(MoveMwrR, offset, ClassReg, TempReg);
+	anInstruction1;
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset1 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction2 = genoperandoperandoperand(MoveMwrR, offset1, ClassReg, TempReg);
+	anInstruction2;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpNonZero: */
+	jumpClassMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin Label */
+	itsAHit = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	/* begin MoveMw:r:R: */
+	offset2 = (((usqInt)(methodCacheAddress()))) + (MethodCacheMethod << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction3 = genoperandoperandoperand(MoveMwrR, offset2, ClassReg, SendNumArgsReg);
+	anInstruction3;
+	genLoadSlotsourceRegdestReg(HeaderIndex, SendNumArgsReg, ClassReg);
+	jumpBCMethod = genJumpImmediate(ClassReg);
+	jmpTarget(jumpBCMethod, picInterpretAbort);
+	/* begin AddCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction4 = genoperandoperand(AddCqR, cmNoCheckEntryOffset, ClassReg);
+	anInstruction4;
+	/* begin JumpR: */
+	genoperand(JumpR, ClassReg);
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpClassMiss, gLabel()));
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, (shiftForWord()) - 1, ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	literal1 = MethodCacheMask << (shiftForWord());
+	anInstruction5 = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction5;
+	/* begin MoveMw:r:R: */
+	offset3 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction6 = genoperandoperandoperand(MoveMwrR, offset3, ClassReg, TempReg);
+	anInstruction6;
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset4 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction7 = genoperandoperandoperand(MoveMwrR, offset4, ClassReg, TempReg);
+	anInstruction7;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	annotateobjRef(gXorCwR(selector, ClassReg), selector);
+	
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	literal2 = MethodCacheMask << (shiftForWord());
+	anInstruction8 = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction8;
+	/* begin MoveMw:r:R: */
+	offset5 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction9 = genoperandoperandoperand(MoveMwrR, offset5, ClassReg, TempReg);
+	anInstruction9;
+	annotateobjRef(gCmpCwR(selector, TempReg), selector);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset6 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction10 = genoperandoperandoperand(MoveMwrR, offset6, ClassReg, TempReg);
+	anInstruction10;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	genPushRegisterArgsForNumArgsscratchReg(backEnd, numArgs, SendNumArgsReg);
+
+	genSmalltalkToCStackSwitch(1);
+	addDependent(methodLabel, annotateAbsolutePCRef(gMoveCwR(((sqInt)methodLabel), SendNumArgsReg)));
+	compileCallFornumArgsargargargargresultRegsaveRegs(ceSendFromInLineCacheMiss, 1, SendNumArgsReg, null, null, null, null, 0);
+}
+
 	/* SimpleStackBasedCogit>>#extendedPushBytecode */
 static sqInt
 extendedPushBytecode(void)
@@ -21117,6 +21278,164 @@
 	return genJumpTo(targetpc);
 }
 
+
+/*	Compile the code for a probe of the first-level method cache for a perform
+	primtiive. The selector is assumed to be in Arg0Reg. Defer to
+	adjustArgumentsForPerform: to
+	adjust the arguments before the jump to the method. */
+
+	/* SimpleStackBasedCogit>>#genLookupForPerformNumArgs: */
+static sqInt
+genLookupForPerformNumArgs(sqInt numArgs)
+{
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    AbstractInstruction *anInstruction10;
+    AbstractInstruction *anInstruction2;
+    AbstractInstruction *anInstruction3;
+    AbstractInstruction *anInstruction4;
+    AbstractInstruction *anInstruction5;
+    AbstractInstruction *anInstruction6;
+    AbstractInstruction *anInstruction7;
+    AbstractInstruction *anInstruction8;
+    AbstractInstruction *anInstruction9;
+    AbstractInstruction *itsAHit;
+    AbstractInstruction *jumpClassMiss;
+    AbstractInstruction *jumpInterpret;
+    AbstractInstruction *jumpSelectorMiss;
+    sqInt offset;
+    sqInt offset1;
+    sqInt offset2;
+    sqInt offset3;
+    sqInt offset4;
+    sqInt offset5;
+    sqInt offset6;
+
+
+	/* N.B.  Can't assume TempReg already contains the tag because a method can
+	   of course be invoked via the unchecked entry-point, e.g. as does perform:. */
+
+	genGetInlineCacheClassTagFromintoforEntry(ReceiverResultReg, ClassReg, 0);
+	flag("lookupInMethodCacheSel:classTag:");
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, shiftForWord(), ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction;
+	/* begin MoveMw:r:R: */
+	offset = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction4 = genoperandoperandoperand(MoveMwrR, offset, ClassReg, TempReg);
+	anInstruction4;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset1 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction5 = genoperandoperandoperand(MoveMwrR, offset1, ClassReg, TempReg);
+	anInstruction5;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpNonZero: */
+	jumpClassMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin Label */
+	itsAHit = genoperandoperand(Label, (labelCounter += 1), bytecodePC);
+	/* begin MoveMw:r:R: */
+	offset2 = (((usqInt)(methodCacheAddress()))) + (MethodCacheMethod << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction6 = genoperandoperandoperand(MoveMwrR, offset2, ClassReg, SendNumArgsReg);
+	anInstruction6;
+	genLoadSlotsourceRegdestReg(HeaderIndex, SendNumArgsReg, ClassReg);
+
+	/* Adjust arguments and jump to the method's unchecked entry-point. */
+
+	jumpInterpret = genJumpImmediate(ClassReg);
+	/* begin AddCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction1 = genoperandoperand(AddCqR, cmNoCheckEntryOffset, ClassReg);
+	anInstruction1;
+	adjustArgumentsForPerform(numArgs);
+	/* begin JumpR: */
+	genoperand(JumpR, ClassReg);
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpClassMiss, gLabel()));
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	/* begin LogicalShiftLeftCq:R: */
+	genoperandoperand(LogicalShiftLeftCqR, (shiftForWord()) - 1, ClassReg);
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction2 = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction2;
+	/* begin MoveMw:r:R: */
+	offset3 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction7 = genoperandoperandoperand(MoveMwrR, offset3, ClassReg, TempReg);
+	anInstruction7;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset4 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction8 = genoperandoperandoperand(MoveMwrR, offset4, ClassReg, TempReg);
+	anInstruction8;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, gLabel());
+	/* begin MoveR:R: */
+	genoperandoperand(MoveRR, SendNumArgsReg, ClassReg);
+	/* begin XorR:R: */
+	genoperandoperand(XorRR, Arg0Reg, ClassReg);
+	
+	/* begin AndCq:R: */
+	/* begin gen:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction3 = genoperandoperand(AndCqR, MethodCacheMask << (shiftForWord()), ClassReg);
+	anInstruction3;
+	/* begin MoveMw:r:R: */
+	offset5 = (((usqInt)(methodCacheAddress()))) + (MethodCacheSelector << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction9 = genoperandoperandoperand(MoveMwrR, offset5, ClassReg, TempReg);
+	anInstruction9;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, Arg0Reg, TempReg);
+	/* begin JumpNonZero: */
+	jumpSelectorMiss = genoperand(JumpNonZero, ((sqInt)0));
+	/* begin MoveMw:r:R: */
+	offset6 = (((usqInt)(methodCacheAddress()))) + (MethodCacheClass << (shiftForWord()));
+	/* begin gen:quickConstant:operand:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction10 = genoperandoperandoperand(MoveMwrR, offset6, ClassReg, TempReg);
+	anInstruction10;
+	/* begin CmpR:R: */
+	genoperandoperand(CmpRR, SendNumArgsReg, TempReg);
+	/* begin JumpZero: */
+	genoperand(JumpZero, ((sqInt)itsAHit));
+	jmpTarget(jumpSelectorMiss, jmpTarget(jumpInterpret, gLabel()));
+	return 0;
+}
+
 	/* SimpleStackBasedCogit>>#genMoveFalseR: */
 static AbstractInstruction *
 genMoveFalseR(sqInt reg)
@@ -22200,6 +22519,75 @@
 }
 
 
+/*	e.g.	Receiver				Receiver
+	Selector/Arg0	=>		Arg1
+	Arg1					Arg2
+	Arg2			sp->	retpc
+	sp->	retpc */
+/*	Generate code to adjust the possibly stacked arguments immediately
+	before jumping to a method looked up by a perform primitive. */
+
+	/* StackToRegisterMappingCogit>>#adjustArgumentsForPerform: */
+static void
+adjustArgumentsForPerform(sqInt numArgs)
+{
+    AbstractInstruction *anInstruction;
+    AbstractInstruction *anInstruction1;
+    AbstractInstruction *anInstruction2;
+    AbstractInstruction *anInstruction3;
+    AbstractInstruction *anInstruction4;
+    sqInt index;
+
+	assert((numRegArgs()) <= 2);
+	assert(numArgs >= 1);
+	if (numArgs <= 2) {
+		if (numArgs == 2) {
+			/* begin MoveR:R: */
+			genoperandoperand(MoveRR, Arg1Reg, Arg0Reg);
+		}
+		return;
+	}
+	if ((2 + 1) == numArgs) {
+		/* begin PopR: */
+		genoperand(PopR, TempReg);
+		/* begin PopR: */
+		genoperand(PopR, Arg1Reg);
+
+		/* begin MoveMw:r:R: */
+		/* begin gen:quickConstant:operand:operand: */
+		/* begin checkQuickConstant:forInstruction: */
+		anInstruction = genoperandoperandoperand(MoveMwrR, 0, SPReg, Arg0Reg);
+		anInstruction;
+		/* begin MoveR:Mw:r: */
+		/* begin gen:operand:quickConstant:operand: */
+		/* begin checkQuickConstant:forInstruction: */
+		anInstruction1 = genoperandoperandoperand(MoveRMwr, TempReg, 0, SPReg);
+		anInstruction1;
+
+		return;
+	}
+	for (index = (numArgs - 1); index >= 0; index += -1) {
+		/* begin MoveMw:r:R: */
+		/* begin gen:quickConstant:operand:operand: */
+		/* begin checkQuickConstant:forInstruction: */
+		anInstruction2 = genoperandoperandoperand(MoveMwrR, index * BytesPerWord, SPReg, TempReg);
+		anInstruction2;
+		/* begin MoveR:Mw:r: */
+		/* begin gen:operand:quickConstant:operand: */
+		/* begin checkQuickConstant:forInstruction: */
+		anInstruction3 = genoperandoperandoperand(MoveRMwr, TempReg, (index + 1) * BytesPerWord, SPReg);
+		anInstruction3;
+	}
+	/* begin PopR: */
+	genoperand(PopR, TempReg);
+	/* begin MoveR:Mw:r: */
+	/* begin gen:operand:quickConstant:operand: */
+	/* begin checkQuickConstant:forInstruction: */
+	anInstruction4 = genoperandoperandoperand(MoveRMwr, TempReg, 0, SPReg);
+	anInstruction4;
+}
+
+
 /*	If the stack entry is already in a register not conflicting with regMask,
 	answers it,
 	else allocate a new register not conflicting with reg mask
@@ -22837,158 +23225,6 @@
 	initSimStackForFramefulMethod(initialPC);
 }
 
-
-/*	Compile the code for an open PIC. Perform a probe of the first-level
-	method lookup cache followed by a call of ceSendFromInLineCacheMiss: if
-	the probe fails.
-	Override to push the register args when calling ceSendFromInLineCacheMiss: */
-
-	/* StackToRegisterMappingCogit>>#compileOpenPIC:numArgs: */
-static void
-compileOpenPICnumArgs(sqInt selector, sqInt numArgs)
-{
-    AbstractInstruction *anInstruction;
-    AbstractInstruction *anInstruction1;
-    AbstractInstruction *anInstruction10;
-    AbstractInstruction *anInstruction2;
-    AbstractInstruction *anInstruction3;
-    AbstractInstruction *anInstruction4;
-    AbstractInstruction *anInstruction5;
-    AbstractInstruction *anInstruction6;
-    AbstractInstruction *anInstruction7;
-    AbstractInstruction *anInstruction8;
-    AbstractInstruction *anInstruction9;
-    AbstractInstruction *itsAHit;
-    AbstractInstruction *jumpBCMethod;
-    AbstractInstruction *jumpClassMiss;
-    AbstractInstruction *jumpSelectorMiss;
-    sqInt offset;
-    sqInt offset1;
-    sqInt offset2;
-    sqInt offset3;
-    sqInt offset4;
-    sqInt offset5;
-    sqInt offset6;
-
-	compilePICAbort(numArgs);
-
-	/* Do first of three probes.  See CoInterpreter>>lookupInMethodCacheSel:classTag: */
-
-	entry = genGetClassTagOfintoscratchReg(ReceiverResultReg, ClassReg, TempReg);
-	flag("lookupInMethodCacheSel:classTag:");
-	/* begin MoveR:R: */
-	genoperandoperand(MoveRR, ClassReg, SendNumArgsReg);

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list