[Vm-dev] [commit][2676] CogVM source as per VMMaker.oscog-eem.261.

commits at squeakvm.org commits at squeakvm.org
Thu Jan 31 01:42:04 UTC 2013


Revision: 2676
Author:   eliot
Date:     2013-01-30 17:42:03 -0800 (Wed, 30 Jan 2013)
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.261.

Move determination of the ammount of headroom to the platform in
osCogStackPageHeadroom (in the various sqFooMain.c files).

Provide a routine to monitor the ammount of unused headroom,
which requires the stack memory be zeroed before use.  Assume
the platform will provide a -reportheadroom flag for enabling the
report.  Provide primitiveMinimumUnusedHeadroom for in-image
access.

Add some asserts to check that a page's frame pointer is always
in range (setHeadFP:andSP:inPage: already did this).

Add the GdbARMPlugin.

Correct cygwin HowToBuilds.

Nuke the sparseimage in the Newspeak mac installer.

Add the named serial port read & write primitives to the SerialPlugin.

Fix change history upload in uploadvms script.

Modified Paths:
--------------
    branches/Cog/cygwinbuild/HowToBuild
    branches/Cog/nscogbuild/cygwinbuild/HowToBuild
    branches/Cog/nscogbuild/macbuild/installer/installer-Darwin.gmk
    branches/Cog/nscogsrc/vm/cogit.c
    branches/Cog/nscogsrc/vm/cogit.h
    branches/Cog/nscogsrc/vm/cogmethod.h
    branches/Cog/nscogsrc/vm/cointerp.c
    branches/Cog/nscogsrc/vm/cointerp.h
    branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
    branches/Cog/nscogsrc/vm/interp.h
    branches/Cog/nscogsrc/vm/vmCallback.h
    branches/Cog/platforms/Mac OS/vm/sqMacMain.c
    branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c
    branches/Cog/platforms/Mac OS/vm/sqPlatformSpecific.h
    branches/Cog/platforms/unix/vm/sqPlatformSpecific.h
    branches/Cog/platforms/unix/vm/sqUnixMain.c
    branches/Cog/platforms/win32/vm/sqPlatformSpecific.h
    branches/Cog/platforms/win32/vm/sqWin32Intel.c
    branches/Cog/platforms/win32/vm/sqWin32Window.c
    branches/Cog/scripts/uploadvms
    branches/Cog/src/plugins/SerialPlugin/SerialPlugin.c
    branches/Cog/src/vm/cogit.c
    branches/Cog/src/vm/cogit.h
    branches/Cog/src/vm/cogmethod.h
    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/src/vm/interp.h
    branches/Cog/src/vm/vmCallback.h

Added Paths:
-----------
    branches/Cog/src/plugins/GdbARMPlugin/
    branches/Cog/src/plugins/GdbARMPlugin/GdbARMPlugin.c

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


Property changes on: branches/Cog
___________________________________________________________________
Modified: svn:ignore
   - README.*
*.app
*.dmg
*.msi
*.tgz
*.zip
Cog.app
CogMT.app
coglinux
cogmtlinux
cogwin
cogmtwin
Newspeak Virtual Machine.app
nsvmwin
nsvmlinux

   + ChangeHistory
MVALOG
README.*
*.app
*.dmg
*.msi
*.tgz
*.zip
cogastlinux
cogdbglinux
coglinux
cogmtlinux
cogwin
cogmtwin
nsvmlinux
nsvmlinuxast
nsvmlinuxdbg
nsvmwin


Modified: branches/Cog/cygwinbuild/HowToBuild
===================================================================
--- branches/Cog/cygwinbuild/HowToBuild	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/cygwinbuild/HowToBuild	2013-01-31 01:42:03 UTC (rev 2676)
@@ -23,7 +23,7 @@
      svn co http://www.squeakvm.org/svn/squeak/branches/Cog oscogvm
 
 3. Open a cygwin bash shell, cd into the cygwinbuild directory and execute
-     mvm
+     ./mvm
 
    Caution: if you previously used the mingw gnutools approach, you probably
    have a path to that 2.x gcc in your Windows PATH.  Make sure that 'which gcc'
@@ -34,7 +34,9 @@
      make  CC=gcc-3 LD=gcc-3 DLLWRAP='dllwrap -mno-cygwin --driver-name gcc-3'
    
 4. At the end of this process you should have a brand new Croquet VM in the
-   cygwinbuild/build/vm folder (make sure you copy Croquet.map along with it)
+   cygwinbuild/build/vm folder (make sure you copy Croquet.map along with it).
+   Putting the relevant sources file(s) (e.g. SqueakV41.sources) in the vm
+   folder is then all you need to use that vm to run images.
 
 N.B. The plugin set is defined by plugins.ext and plugins.int in the build dir.
 

Modified: branches/Cog/nscogbuild/cygwinbuild/HowToBuild
===================================================================
--- branches/Cog/nscogbuild/cygwinbuild/HowToBuild	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogbuild/cygwinbuild/HowToBuild	2013-01-31 01:42:03 UTC (rev 2676)
@@ -24,7 +24,7 @@
 
 3. Open a cygwin bash shell, cd into the nscogbuild/cygwinbuild directory and
    execute
-     mvm
+     ./mvm
 
    Caution: if you previously used the mingw gnutools approach, you probably
    have a path to that 2.x gcc in your Windows PATH.  Make sure that 'which gcc'

Modified: branches/Cog/nscogbuild/macbuild/installer/installer-Darwin.gmk
===================================================================
--- branches/Cog/nscogbuild/macbuild/installer/installer-Darwin.gmk	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogbuild/macbuild/installer/installer-Darwin.gmk	2013-01-31 01:42:03 UTC (rev 2676)
@@ -2,7 +2,7 @@
 
 $(VM_DMG): $(VM_BUNDLE) $(INSTALLER_BACKGROUND).png LayoutDiskImage.applescript $(INSTALLER_ICON).icns
 	-hdiutil eject '/Volumes/$(PRODUCT_NAME)'
-	-rm -f  "$@.sparseimage" "$@"
+	-rm -f "$@.sparseimage" "$@"
 	hdiutil create -size 100m -type SPARSE -volname $(VM_LOCALIZED_NAME_ESC) -fs 'Journaled HFS+' "$@.sparseimage"
 	hdiutil attach "$@.sparseimage"
 	mkdir -p '/Volumes/$(PRODUCT_NAME)/.background'
@@ -15,6 +15,7 @@
 	osascript LayoutDiskImage.applescript
 	while test -e '/Volumes/$(PRODUCT_NAME)' ; do echo Waiting for Finder to eject '/Volumes/$(PRODUCT_NAME)'; sleep 2; done
 	hdiutil convert "$@.sparseimage" -format UDBZ -o $(VM_DMG)
+	-rm -f "$@.sparseimage"
 
 .DEFAULT_GOAL := $(VM_DMG)
 

Modified: branches/Cog/nscogsrc/vm/cogit.c
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/cogit.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.256 uuid: bfea3efd-4e81-4e85-922e-cf4f58ee5d64
+	CCodeGenerator VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
    from
-	StackToRegisterMappingCogit VMMaker.oscog-eem.256 uuid: bfea3efd-4e81-4e85-922e-cf4f58ee5d64
+	StackToRegisterMappingCogit VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
-static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.256 uuid: bfea3efd-4e81-4e85-922e-cf4f58ee5d64 " __DATE__ ;
+static char __buildInfo[] = "StackToRegisterMappingCogit VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623 " __DATE__ ;
 char *__cogitBuildInfo = __buildInfo;
 
 
@@ -241,6 +241,7 @@
 #define Label 1
 #define LastJump 39
 #define LFENCE 107
+#define LinkReg -17
 #define LOCK 110
 #define LoadEffectiveAddressMwrR 67
 #define LogicalShiftLeftCqR 73
@@ -1015,7 +1016,6 @@
 static CogSimStackEntry ssTopDescriptor(void);
 static CogSimStackEntry * ssValue(sqInt n);
 static sqInt stackBytesForNumArgs(AbstractInstruction * self_in_stackBytesForNumArgs, sqInt numArgs);
-sqInt stackPageHeadroomBytes(void);
 static sqInt stackPageInterruptHeadroomBytes(AbstractInstruction * self_in_stackPageInterruptHeadroomBytes);
 static void storeLiteralbeforeFollowingAddress(AbstractInstruction * self_in_storeLiteralbeforeFollowingAddress, sqInt literal, sqInt followingAddress);
 static void storeToReg(CogSimStackEntry * self_in_storeToReg, sqInt reg);
@@ -3721,6 +3721,10 @@
 
 	/* begin MoveCq:R: */
 	stackOverflowCall = genoperandoperand(MoveCqR, 0, ReceiverResultReg);
+	if (hasLinkRegister(backEnd)) {
+		/* begin PushR: */
+		genoperand(PushR, LinkReg);
+	}
 	/* begin Call: */
 	callTarget = methodAbortTrampolineFor(methodOrBlockNumArgs);
 	sendMissCall = genoperand(Call, callTarget);
@@ -4871,10 +4875,16 @@
 	back in resultRegOrNil.
 	Hack: a negative value indicates an abstract register, a non-negative
 	value indicates a constant. */
+/*	If on a RISC processor the return address needs to be pushed to the
+	stack so that the interpreter sees the same stack layout as on CISC. */
 
 static void
 compileTrampolineForcallJumpBarnumArgsargargargargsaveRegsresultReg(void *aRoutine, sqInt callJumpBar, sqInt numArgs, sqInt regOrConst0, sqInt regOrConst1, sqInt regOrConst2, sqInt regOrConst3, sqInt saveRegs, sqInt resultRegOrNil)
 {
+	if (hasLinkRegister(backEnd)) {
+		/* begin PushR: */
+		genoperand(PushR, LinkReg);
+	}
 	genSaveStackPointers();
 	genLoadCStackPointers();
 	if (cStackAlignment > BytesPerWord) {
@@ -4940,6 +4950,10 @@
 			}
 		}
 		genLoadStackPointers();
+		if (hasLinkRegister(backEnd)) {
+			/* begin PopR: */
+			genoperand(PopR, LinkReg);
+		}
 		/* begin RetN: */
 		genoperand(RetN, 0);
 	}
@@ -17812,15 +17826,6 @@
 }
 
 
-/*	Delegate this to the processor... */
-
-sqInt
-stackPageHeadroomBytes(void)
-{
-	return stackPageInterruptHeadroomBytes(backEnd);
-}
-
-
 /*	Return a minimum amount of headroom for each stack page (in bytes). In a
 	JIT the stack has to have room for interrupt handlers which will run on
 	the stack.

Modified: branches/Cog/nscogsrc/vm/cogit.h
===================================================================
--- branches/Cog/nscogsrc/vm/cogit.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/cogit.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.256 uuid: bfea3efd-4e81-4e85-922e-cf4f58ee5d64
+	CCodeGenerator VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
 
 
@@ -66,7 +66,6 @@
 void setBreakMethod(sqInt anObj);
 void setPostCompileHook(void (*aFunction)(CogMethod *, void *));
 void setSelectorOfto(CogMethod *cogMethod, sqInt aSelectorOop);
-sqInt stackPageHeadroomBytes(void);
 sqInt traceLinkedSendOffset(void);
 void unlinkAllSends(void);
 void unlinkSendsOfisMNUSelector(sqInt selector, sqInt isMNUSelector);

Modified: branches/Cog/nscogsrc/vm/cogmethod.h
===================================================================
--- branches/Cog/nscogsrc/vm/cogmethod.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/cogmethod.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGenerator VMMaker.oscog-eem.256 uuid: bfea3efd-4e81-4e85-922e-cf4f58ee5d64
+	CCodeGenerator VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
 
 typedef struct {

Modified: branches/Cog/nscogsrc/vm/cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/cointerp.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,9 +1,9 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
    from
-	CoInterpreter VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CoInterpreter VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -715,6 +715,7 @@
 CogMethod * mframeHomeMethod(char *theFP);
 static sqInt mframeIsBlockActivation(char *theFP);
 static sqInt mframeReceiver(char *theFP);
+static sqInt minimumUnusedHeadroom(void);
 sqInt mMethodClass(void);
 static sqInt mnuMethodOrNilFor(sqInt rcvr);
 EXPORT(void) moduleUnloaded(char *aModuleName);
@@ -904,6 +905,7 @@
 EXPORT(void) primitiveMethodXray(void);
 static void primitiveMillisecondClock(void);
 EXPORT(sqInt) primitiveMillisecondClockMask(void);
+EXPORT(void) primitiveMinimumUnusedHeadroom(void);
 static void primitiveMod(void);
 EXPORT(void) primitiveModLargeIntegers(void);
 static void primitiveMouseButtons(void);
@@ -1065,6 +1067,7 @@
 static sqInt removeFirstLinkOfList(sqInt aList);
 EXPORT(sqInt) removeGCRoot(sqInt *varLoc);
 static sqInt removeYoungRoot(sqInt obj);
+void reportMinimumUnusedHeadroom(void);
 static void restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut);
 static sqInt resumepreemptedYieldingIffrom(sqInt aProcess, sqInt yieldImplicitly, sqInt sourceCode);
 EXPORT(sqInt) returnAsThroughCallbackContext(sqInt returnTypeOop, VMCallbackContext *vmCallbackContext, sqInt callbackMethodContext);
@@ -1210,8 +1213,8 @@
 _iss usqInt memoryLimit;
 _iss usqInt endOfMemory;
 _iss StackPage * mostRecentlyUsedPage;
+_iss sqInt numStackPages;
 _iss usqInt scavengeThreshold;
-_iss sqInt numStackPages;
 _iss unsigned char primTraceLogIndex;
 _iss sqLong nextProfileTick;
 _iss sqInt needGCFlag;
@@ -1937,7 +1940,7 @@
  0 };
 static void (*externalPrimitiveTable[MaxExternalPrimitiveTableSize + 1 /* 4097 */])(void);
 static usqInt heapBase;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.258";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.261";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -2013,9 +2016,11 @@
 		stackPageBytes = stackPageByteSize();
 		stackPagesBytes = (GIV(numStackPages) * ((sizeof(CogStackPage)) + (stackPageByteSize()))) + BytesPerWord;
 		theStackMemory = alloca(stackPagesBytes);
+		memset(theStackMemory, 0, stackPagesBytes);
 		sqMakeMemoryNotExecutableFromTo(((usqInt)(startOfMemory())), ((usqInt)GIV(memoryLimit)));
 		sqMakeMemoryNotExecutableFromTo(((usqInt)theStackMemory), (((usqInt)theStackMemory)) + stackPagesBytes);
 		initializeStacknumSlotspageSize(theStackMemory, ((sqInt) stackPagesBytes >> 2), ((sqInt) stackPageBytes >> 2));
+		assert((minimumUnusedHeadroom()) == stackPageBytes);
 		loadInitialContext();
 		ioInitHeartbeat();
 		initialEnterSmalltalkExecutive();
@@ -23718,7 +23723,7 @@
 		page = stackPageAtpages(index, GIV(pages));
 		(page->lastAddress = theStackPages + (index * GIV(bytesPerPage)));
 		(page->baseAddress = ((page->lastAddress)) + GIV(bytesPerPage));
-		(page->stackLimit = ((page->baseAddress)) - (((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024)))));
+		(page->stackLimit = ((page->baseAddress)) - (((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom()))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom())))));
 		(page->realStackLimit = (page->stackLimit));
 		(page->baseFP = 0);
 		(page->nextPage = stackPageAt((index == (numPages - 1)
@@ -24218,6 +24223,8 @@
 			assert((isOopCompiledMethod(GIV(newMethod)))
 			 && ((primitiveIndexOf(GIV(newMethod))) != 0));
 		}
+		assert((GIV(framePointer) < ((GIV(stackPage)->baseAddress)))
+		 && (GIV(framePointer) > (((GIV(stackPage)->realStackLimit)) - (((sqInt) LargeContextSize >> 1)))));
 		(GIV(stackPage)->headFP = GIV(framePointer));
 		if ((((unsigned long) primitiveFunctionPointer)) <= MaxQuickPrimitiveIndex) {
 			externalQuickPrimitiveResponse();
@@ -28145,6 +28152,39 @@
 	return longAt(theFP + FoxMFReceiver);
 }
 
+
+/*	Traverse all stack pages looking for non-zero bytes in the headroom part
+	of each page.
+	Answer the minimum size of unused headroom (zero bytes) in the pages. This
+	is for
+	checking that there is enough headroom allocated in stack pages. */
+
+static sqInt
+minimumUnusedHeadroom(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt i;
+    sqInt minUnused;
+    char *p;
+    StackPage *page;
+    sqInt unused;
+
+	minUnused = ((stackPageAt(0)->baseAddress)) - ((stackPageAt(0)->lastAddress));
+	for (i = 0; i <= (GIV(numStackPages) - 1); i += 1) {
+		/* begin stackPageAt: */
+		page = stackPageAtpages(i, GIV(pages));
+		p = (page->lastAddress);
+		do {
+			p += BytesPerWord;
+		} while(((longAtPointer(p)) == 0)
+ && (p <= ((page->baseAddress))));
+		unused = (p - BytesPerWord) - ((page->lastAddress));
+		if (unused < minUnused) {
+			minUnused = unused;
+		}
+	}
+	return minUnused;
+}
+
 sqInt
 mMethodClass(void)
 {
@@ -28335,6 +28375,8 @@
 		callerIP = ceReturnToInterpreterPC();
 	}
 	longAtput(theFP + stackedReceiverOffset, callerIP);
+	assert((callerFP < ((oldPage->baseAddress)))
+	 && (callerFP > (((oldPage->realStackLimit)) - (((sqInt) LargeContextSize >> 1)))));
 	(oldPage->headFP = callerFP);
 	(oldPage->headSP = theFP + stackedReceiverOffset);
 	longAtput(newFP + FoxCallerSavedIP, ceBaseFrameReturnPC());
@@ -38381,6 +38423,20 @@
 	GIV(stackPointer) = sp;
 }
 
+EXPORT(void)
+primitiveMinimumUnusedHeadroom(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt oop;
+    char *sp;
+
+	/* begin methodReturnValue: */
+	oop = (((minimumUnusedHeadroom()) << 1) | 1);
+	/* begin pop:thenPush: */
+	longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), oop);
+	GIV(stackPointer) = sp;
+	0;
+}
+
 static void
 primitiveMod(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
@@ -47257,6 +47313,15 @@
 }
 
 
+/*	Report the stack page size and minimum unused headroom to stdout. */
+
+void
+reportMinimumUnusedHeadroom(void)
+{
+	printf("stack page size %ld minimum unused stack headroom %ld bytes\n", stackPageByteSize(), minimumUnusedHeadroom());
+}
+
+
 /*	Restore headers smashed by forwarding links */
 
 static void
@@ -49548,7 +49613,7 @@
 static sqInt
 stackLimitBytes(void)
 {
-	return ((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024)));
+	return ((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom()))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom())));
 }
 
 
@@ -49625,7 +49690,7 @@
     sqInt pageBytes;
     sqInt smallSize;
 
-	pageBytes = (512 + ((IFrameSlots + 64) * BytesPerWord)) + ((stackPageHeadroomBytes()) + 1024);
+	pageBytes = (512 + ((IFrameSlots + 64) * BytesPerWord)) + (osCogStackPageHeadroom());
 	if ((pageBytes & (pageBytes - 1)) == 0) {
 
 		/* = 0 => a power of two */
@@ -49658,14 +49723,14 @@
 
 
 /*	Return a minimum amount of headroom for each stack page (in bytes).
-	In a JIT the stack has to have room for interrupt handlers which will run
-	on the
-	stack. In the interpreter we don't actually need any headroom. */
+	In the interpreter we don't actually need any headroom. In a JIT the stack
+	has to have room for interrupt handlers which will run on the stack.
+	Defer to the platform for this one. */
 
 static sqInt
 stackPageHeadroom(void)
 {
-	return (stackPageHeadroomBytes()) + 1024;
+	return osCogStackPageHeadroom();
 }
 
 usqInt
@@ -52294,6 +52359,7 @@
 	{"", "primitiveLongRunningPrimitiveSemaphore", (void*)primitiveLongRunningPrimitiveSemaphore},
 	{"", "primitiveMethodXray", (void*)primitiveMethodXray},
 	{"", "primitiveMillisecondClockMask", (void*)primitiveMillisecondClockMask},
+	{"", "primitiveMinimumUnusedHeadroom", (void*)primitiveMinimumUnusedHeadroom},
 	{"", "primitiveModLargeIntegers", (void*)primitiveModLargeIntegers},
 	{"", "primitiveMultiplyLargeIntegers", (void*)primitiveMultiplyLargeIntegers},
 	{"", "primitiveNotEqualLargeIntegers", (void*)primitiveNotEqualLargeIntegers},

Modified: branches/Cog/nscogsrc/vm/cointerp.h
===================================================================
--- branches/Cog/nscogsrc/vm/cointerp.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/cointerp.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
 
 
@@ -173,6 +173,7 @@
 sqInt rawHeaderOf(sqInt methodPointer);
 void rawHeaderOfput(sqInt methodOop, sqInt cogMethodOrMethodHeader);
 sqInt remap(sqInt oop);
+void reportMinimumUnusedHeadroom(void);
 usqInt scavengeThresholdAddress(void);
 void scheduleIncrementalGC(void);
 void setBreakSelector(char *aString);

Modified: branches/Cog/nscogsrc/vm/gcc3x-cointerp.c
===================================================================
--- branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/gcc3x-cointerp.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -2,11 +2,11 @@
 
 
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
    from
-	CoInterpreter VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CoInterpreter VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
-static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea " __DATE__ ;
+static char __buildInfo[] = "CoInterpreter VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623 " __DATE__ ;
 char *__interpBuildInfo = __buildInfo;
 
 
@@ -718,6 +718,7 @@
 CogMethod * mframeHomeMethod(char *theFP);
 static sqInt mframeIsBlockActivation(char *theFP);
 static sqInt mframeReceiver(char *theFP);
+static sqInt minimumUnusedHeadroom(void);
 sqInt mMethodClass(void);
 static sqInt mnuMethodOrNilFor(sqInt rcvr);
 EXPORT(void) moduleUnloaded(char *aModuleName);
@@ -907,6 +908,7 @@
 EXPORT(void) primitiveMethodXray(void);
 static void primitiveMillisecondClock(void);
 EXPORT(sqInt) primitiveMillisecondClockMask(void);
+EXPORT(void) primitiveMinimumUnusedHeadroom(void);
 static void primitiveMod(void);
 EXPORT(void) primitiveModLargeIntegers(void);
 static void primitiveMouseButtons(void);
@@ -1068,6 +1070,7 @@
 static sqInt removeFirstLinkOfList(sqInt aList);
 EXPORT(sqInt) removeGCRoot(sqInt *varLoc);
 static sqInt removeYoungRoot(sqInt obj);
+void reportMinimumUnusedHeadroom(void);
 static void restoreHeadersFromtofromandtofrom(sqInt firstIn, sqInt lastIn, sqInt hdrBaseIn, sqInt firstOut, sqInt lastOut, sqInt hdrBaseOut);
 static sqInt resumepreemptedYieldingIffrom(sqInt aProcess, sqInt yieldImplicitly, sqInt sourceCode);
 EXPORT(sqInt) returnAsThroughCallbackContext(sqInt returnTypeOop, VMCallbackContext *vmCallbackContext, sqInt callbackMethodContext);
@@ -1213,8 +1216,8 @@
 _iss usqInt memoryLimit;
 _iss usqInt endOfMemory;
 _iss StackPage * mostRecentlyUsedPage;
+_iss sqInt numStackPages;
 _iss usqInt scavengeThreshold;
-_iss sqInt numStackPages;
 _iss unsigned char primTraceLogIndex;
 _iss sqLong nextProfileTick;
 _iss sqInt needGCFlag;
@@ -1940,7 +1943,7 @@
  0 };
 static void (*externalPrimitiveTable[MaxExternalPrimitiveTableSize + 1 /* 4097 */])(void);
 static usqInt heapBase;
-const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.258";
+const char *interpreterVersion = "Newspeak Virtual Machine CoInterpreter_VMMaker.oscog-eem.261";
 sqInt minBackwardJumpCountForCompile = MinBackwardJumpCountForCompile /* 10 */;
 volatile int sendTrace;
 
@@ -2022,9 +2025,11 @@
 		stackPageBytes = stackPageByteSize();
 		stackPagesBytes = (GIV(numStackPages) * ((sizeof(CogStackPage)) + (stackPageByteSize()))) + BytesPerWord;
 		theStackMemory = alloca(stackPagesBytes);
+		memset(theStackMemory, 0, stackPagesBytes);
 		sqMakeMemoryNotExecutableFromTo(((usqInt)(startOfMemory())), ((usqInt)GIV(memoryLimit)));
 		sqMakeMemoryNotExecutableFromTo(((usqInt)theStackMemory), (((usqInt)theStackMemory)) + stackPagesBytes);
 		initializeStacknumSlotspageSize(theStackMemory, ((sqInt) stackPagesBytes >> 2), ((sqInt) stackPageBytes >> 2));
+		assert((minimumUnusedHeadroom()) == stackPageBytes);
 		loadInitialContext();
 		ioInitHeartbeat();
 		initialEnterSmalltalkExecutive();
@@ -23727,7 +23732,7 @@
 		page = stackPageAtpages(index, GIV(pages));
 		(page->lastAddress = theStackPages + (index * GIV(bytesPerPage)));
 		(page->baseAddress = ((page->lastAddress)) + GIV(bytesPerPage));
-		(page->stackLimit = ((page->baseAddress)) - (((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024)))));
+		(page->stackLimit = ((page->baseAddress)) - (((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom()))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom())))));
 		(page->realStackLimit = (page->stackLimit));
 		(page->baseFP = 0);
 		(page->nextPage = stackPageAt((index == (numPages - 1)
@@ -24227,6 +24232,8 @@
 			assert((isOopCompiledMethod(GIV(newMethod)))
 			 && ((primitiveIndexOf(GIV(newMethod))) != 0));
 		}
+		assert((GIV(framePointer) < ((GIV(stackPage)->baseAddress)))
+		 && (GIV(framePointer) > (((GIV(stackPage)->realStackLimit)) - (((sqInt) LargeContextSize >> 1)))));
 		(GIV(stackPage)->headFP = GIV(framePointer));
 		if ((((unsigned long) primitiveFunctionPointer)) <= MaxQuickPrimitiveIndex) {
 			externalQuickPrimitiveResponse();
@@ -28154,6 +28161,39 @@
 	return longAt(theFP + FoxMFReceiver);
 }
 
+
+/*	Traverse all stack pages looking for non-zero bytes in the headroom part
+	of each page.
+	Answer the minimum size of unused headroom (zero bytes) in the pages. This
+	is for
+	checking that there is enough headroom allocated in stack pages. */
+
+static sqInt
+minimumUnusedHeadroom(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt i;
+    sqInt minUnused;
+    char *p;
+    StackPage *page;
+    sqInt unused;
+
+	minUnused = ((stackPageAt(0)->baseAddress)) - ((stackPageAt(0)->lastAddress));
+	for (i = 0; i <= (GIV(numStackPages) - 1); i += 1) {
+		/* begin stackPageAt: */
+		page = stackPageAtpages(i, GIV(pages));
+		p = (page->lastAddress);
+		do {
+			p += BytesPerWord;
+		} while(((longAtPointer(p)) == 0)
+ && (p <= ((page->baseAddress))));
+		unused = (p - BytesPerWord) - ((page->lastAddress));
+		if (unused < minUnused) {
+			minUnused = unused;
+		}
+	}
+	return minUnused;
+}
+
 sqInt
 mMethodClass(void)
 {
@@ -28344,6 +28384,8 @@
 		callerIP = ceReturnToInterpreterPC();
 	}
 	longAtput(theFP + stackedReceiverOffset, callerIP);
+	assert((callerFP < ((oldPage->baseAddress)))
+	 && (callerFP > (((oldPage->realStackLimit)) - (((sqInt) LargeContextSize >> 1)))));
 	(oldPage->headFP = callerFP);
 	(oldPage->headSP = theFP + stackedReceiverOffset);
 	longAtput(newFP + FoxCallerSavedIP, ceBaseFrameReturnPC());
@@ -38390,6 +38432,20 @@
 	GIV(stackPointer) = sp;
 }
 
+EXPORT(void)
+primitiveMinimumUnusedHeadroom(void)
+{   DECL_MAYBE_SQ_GLOBAL_STRUCT
+    sqInt oop;
+    char *sp;
+
+	/* begin methodReturnValue: */
+	oop = (((minimumUnusedHeadroom()) << 1) | 1);
+	/* begin pop:thenPush: */
+	longAtput((sp = GIV(stackPointer) + (((GIV(argumentCount) + 1) - 1) * BytesPerWord)), oop);
+	GIV(stackPointer) = sp;
+	0;
+}
+
 static void
 primitiveMod(void)
 {   DECL_MAYBE_SQ_GLOBAL_STRUCT
@@ -47266,6 +47322,15 @@
 }
 
 
+/*	Report the stack page size and minimum unused headroom to stdout. */
+
+void
+reportMinimumUnusedHeadroom(void)
+{
+	printf("stack page size %ld minimum unused stack headroom %ld bytes\n", stackPageByteSize(), minimumUnusedHeadroom());
+}
+
+
 /*	Restore headers smashed by forwarding links */
 
 static void
@@ -49557,7 +49622,7 @@
 static sqInt
 stackLimitBytes(void)
 {
-	return ((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - ((stackPageHeadroomBytes()) + 1024)));
+	return ((512 < (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom()))) ? 512 : (((stackPageByteSize()) - ((IFrameSlots + 64) * BytesPerWord)) - (osCogStackPageHeadroom())));
 }
 
 
@@ -49634,7 +49699,7 @@
     sqInt pageBytes;
     sqInt smallSize;
 
-	pageBytes = (512 + ((IFrameSlots + 64) * BytesPerWord)) + ((stackPageHeadroomBytes()) + 1024);
+	pageBytes = (512 + ((IFrameSlots + 64) * BytesPerWord)) + (osCogStackPageHeadroom());
 	if ((pageBytes & (pageBytes - 1)) == 0) {
 
 		/* = 0 => a power of two */
@@ -49667,14 +49732,14 @@
 
 
 /*	Return a minimum amount of headroom for each stack page (in bytes).
-	In a JIT the stack has to have room for interrupt handlers which will run
-	on the
-	stack. In the interpreter we don't actually need any headroom. */
+	In the interpreter we don't actually need any headroom. In a JIT the stack
+	has to have room for interrupt handlers which will run on the stack.
+	Defer to the platform for this one. */
 
 static sqInt
 stackPageHeadroom(void)
 {
-	return (stackPageHeadroomBytes()) + 1024;
+	return osCogStackPageHeadroom();
 }
 
 usqInt
@@ -52303,6 +52368,7 @@
 	{"", "primitiveLongRunningPrimitiveSemaphore", (void*)primitiveLongRunningPrimitiveSemaphore},
 	{"", "primitiveMethodXray", (void*)primitiveMethodXray},
 	{"", "primitiveMillisecondClockMask", (void*)primitiveMillisecondClockMask},
+	{"", "primitiveMinimumUnusedHeadroom", (void*)primitiveMinimumUnusedHeadroom},
 	{"", "primitiveModLargeIntegers", (void*)primitiveModLargeIntegers},
 	{"", "primitiveMultiplyLargeIntegers", (void*)primitiveMultiplyLargeIntegers},
 	{"", "primitiveNotEqualLargeIntegers", (void*)primitiveNotEqualLargeIntegers},

Modified: branches/Cog/nscogsrc/vm/interp.h
===================================================================
--- branches/Cog/nscogsrc/vm/interp.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/interp.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
 
 #define VM_PROXY_MAJOR 1

Modified: branches/Cog/nscogsrc/vm/vmCallback.h
===================================================================
--- branches/Cog/nscogsrc/vm/vmCallback.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/nscogsrc/vm/vmCallback.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -1,5 +1,5 @@
 /* Automatically generated by
-	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.258 uuid: da1433f1-de50-475f-be33-f462b300a2ea
+	CCodeGeneratorGlobalStructure VMMaker.oscog-eem.261 uuid: eeb310a3-23e0-41f6-8a92-5749b798e623
  */
 
 #define VM_CALLBACK_INC 1


Property changes on: branches/Cog/platforms/Cross/vm/sqSCCSVersion.h
___________________________________________________________________
Modified: checkindate
   - Fri Jan 18 11:18:01 PST 2013
   + Wed Jan 30 17:41:13 PST 2013

Modified: branches/Cog/platforms/Mac OS/vm/sqMacMain.c
===================================================================
--- branches/Cog/platforms/Mac OS/vm/sqMacMain.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/Mac OS/vm/sqMacMain.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -77,6 +77,7 @@
 #include <objc/objc-runtime.h>
 
 #include "sq.h"
+#include "sqAssert.h"
 #include "sqMacUIConstants.h"
 #include "sqMacMain.h"
 #include "sqMacUIMenuBar.h"
@@ -107,6 +108,7 @@
 # include <execinfo.h>
 # define BACKTRACE_DEPTH 64
 #endif
+#include <signal.h>
 #include <sys/ucontext.h>
 
 extern pthread_mutex_t gEventQueueLock,gSleepLock;
@@ -235,6 +237,10 @@
 #if STACKVM
 	printf("\nMost recent primitives\n");
 	dumpPrimTraceLog();
+# if COGVM
+	printf("\n");
+	reportMinimumUnusedHeadroom();
+# endif
 #endif
 	printf("\n\t(%s)\n", msg);
 	fflush(stdout);
@@ -541,6 +547,11 @@
 ioExitWithErrorCode(int ec)
 {
 	extern void printPhaseTime(int);
+#if COGVM
+extern sqInt reportStackHeadroom;
+	if (reportStackHeadroom)
+		reportMinimumUnusedHeadroom();
+#endif
 	printPhaseTime(3);
     UnloadScrap();
     ioShutdownAllModules();
@@ -1018,6 +1029,8 @@
  * Support code for Cog.
  * a) Answer whether the C frame pointer is in use, for capture of the C stack
  *    pointers.
+ * b) answer the amount of stack room to ensure in a Cog stack page, including
+ *    the size of the redzone, if any.
  */
 # if defined(i386) || defined(__i386) || defined(__i386__)
 /*
@@ -1040,4 +1053,51 @@
 	return CFramePointer >= CStackPointer && CFramePointer <= currentCSP;
 }
 # endif /* defined(i386) || defined(__i386) || defined(__i386__) */
+
+/* Answer an approximation of the size of the redzone (if any).  Do so by
+ * sending a signal to the process and computing the difference between the
+ * stack pointer in the signal handler and that in the caller. Assumes stacks
+ * descend.
+ */
+
+#if !defined(min)
+# define min(x,y) (((x)>(y))?(y):(x))
+#endif
+static char *p = 0;
+
+static void
+sighandler(int sig) { p = (char *)&sig; }
+
+static int
+getRedzoneSize()
+{
+	struct sigaction handler_action, old;
+	handler_action.sa_sigaction = sighandler;
+	handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
+	sigemptyset(&handler_action.sa_mask);
+	(void)sigaction(SIGPROF, &handler_action, &old);
+
+	do kill(getpid(),SIGPROF); while (!p);
+	(void)sigaction(SIGPROF, &old, 0);
+	return (char *)min(&old,&handler_action) - sizeof(struct sigaction) - p;
+}
+
+sqInt reportStackHeadroom;
+static int stackPageHeadroom;
+
+/* Answer the redzone size plus space for any signal handlers to run in.
+ * N.B. Space for signal handers may include space for the dynamic linker to
+ * run in since signal handlers may reference other functions, and linking may
+ * be lazy.  The reportheadroom switch can be used to check empirically that
+ * there is sufficient headroom.  At least on Mac OS X we see no large stack
+ * usage that would indicate e.g. dynamic linking in signal handlers.
+ * So answer only the redzone size and likely get small (2048 byte) pages.
+ */
+int
+osCogStackPageHeadroom()
+{
+	if (!stackPageHeadroom)
+		stackPageHeadroom = getRedzoneSize();
+	return stackPageHeadroom;
+}
 #endif /* COGVM */

Modified: branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c
===================================================================
--- branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/Mac OS/vm/sqMacUnixCommandLineInterface.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -205,6 +205,10 @@
 		extern sqInt pollpip;
 		pollpip = atoi(argv[1]);	 
 		return 2; }
+      else if (!strcmp(argv[0], "-reportheadroom")) { 
+		extern sqInt reportStackHeadroom;
+		reportStackHeadroom = 1;
+		return 1; }
 #endif /* STACKVM */
 #if COGVM
       else if (!strcmp(argv[0], "-codesize")) { 

Modified: branches/Cog/platforms/Mac OS/vm/sqPlatformSpecific.h
===================================================================
--- branches/Cog/platforms/Mac OS/vm/sqPlatformSpecific.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/Mac OS/vm/sqPlatformSpecific.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -133,6 +133,8 @@
 extern void sqMakeMemoryNotExecutableFromTo(unsigned long, unsigned long);
 
 extern int isCFramePointerInUse(void);
+extern int osCogStackPageHeadroom(void);
+extern void reportMinimumUnusedHeadroom(void);
 #endif
 
 /* warnPrintf is provided (and needed) on the win32 platform.

Modified: branches/Cog/platforms/unix/vm/sqPlatformSpecific.h
===================================================================
--- branches/Cog/platforms/unix/vm/sqPlatformSpecific.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/unix/vm/sqPlatformSpecific.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -52,6 +52,8 @@
 extern void sqMakeMemoryNotExecutableFromTo(unsigned long, unsigned long);
 
 extern int isCFramePointerInUse(void);
+extern int osCogStackPageHeadroom(void);
+extern void reportMinimumUnusedHeadroom(void);
 #endif
 
 /* warnPrintf is provided (and needed) on the win32 platform.

Modified: branches/Cog/platforms/unix/vm/sqUnixMain.c
===================================================================
--- branches/Cog/platforms/unix/vm/sqUnixMain.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/unix/vm/sqUnixMain.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -34,6 +34,7 @@
  */
 
 #include "sq.h"
+#include "sqAssert.h"
 #include "sqMemoryAccess.h"
 #include "sqaio.h"
 #include "sqUnixCharConv.h"
@@ -851,6 +852,10 @@
 #if STACKVM
 	printf("\nMost recent primitives\n");
 	dumpPrimTraceLog();
+# if COGVM
+	printf("\n");
+	reportMinimumUnusedHeadroom();
+# endif
 #endif
 	printf("\n\t(%s)\n", msg);
 	fflush(stdout);
@@ -1363,6 +1368,10 @@
 		extern sqInt pollpip;
 		pollpip = atoi(argv[1]);	 
 		return 2; }
+      else if (!strcmp(argv[0], "-reportheadroom")) { 
+		extern sqInt reportStackHeadroom;
+		reportStackHeadroom = 1;
+		return 1; }
 #endif /* STACKVM */
 #if COGVM
       else if (!strcmp(argv[0], "-codesize")) { 
@@ -1857,6 +1866,11 @@
 sqInt
 ioExitWithErrorCode(int ec)
 {
+#if COGVM
+extern sqInt reportStackHeadroom;
+	if (reportStackHeadroom)
+		reportMinimumUnusedHeadroom();
+#endif
   printPhaseTime(3);
   dpy->winExit();
   exit(ec);
@@ -1952,6 +1966,8 @@
  * Support code for Cog.
  * a) Answer whether the C frame pointer is in use, for capture of the C stack
  *    pointers.
+ * b) answer the amount of stack room to ensure in a Cog stack page, including
+ *    the size of the redzone, if any.
  */
 # if defined(i386) || defined(__i386) || defined(__i386__)
 /*
@@ -1974,4 +1990,49 @@
 	return CFramePointer >= CStackPointer && CFramePointer <= currentCSP;
 }
 # endif /* defined(i386) || defined(__i386) || defined(__i386__) */
+
+/* Answer an approximation of the size of the redzone (if any).  Do so by
+ * sending a signal to the process and computing the difference between the
+ * stack pointer in the signal handler and that in the caller. Assumes stacks
+ * descend.
+ */
+
+#if !defined(min)
+# define min(x,y) (((x)>(y))?(y):(x))
+#endif
+static char *p = 0;
+
+static void
+sighandler(int sig) { p = (char *)&sig; }
+
+static int
+getRedzoneSize()
+{
+	struct sigaction handler_action, old;
+	handler_action.sa_sigaction = sighandler;
+	handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
+	sigemptyset(&handler_action.sa_mask);
+	(void)sigaction(SIGPROF, &handler_action, &old);
+
+	do kill(getpid(),SIGPROF); while (!p);
+	(void)sigaction(SIGPROF, &old, 0);
+	return (char *)min(&old,&handler_action) - sizeof(struct sigaction) - p;
+}
+
+sqInt reportStackHeadroom;
+static int stackPageHeadroom;
+
+/* Answer the redzone size plus space for any signal handlers to run in.
+ * N.B. Space for signal handers may include space for the dynamic linker to
+ * run in since signal handlers may reference other functions, and linking may
+ * be lazy.  The reportheadroom switch can be used to check empirically that
+ * there is sufficient headroom.
+ */
+int
+osCogStackPageHeadroom()
+{
+	if (!stackPageHeadroom)
+		stackPageHeadroom = getRedzoneSize() + 1024;
+	return stackPageHeadroom;
+}
 #endif /* COGVM */

Modified: branches/Cog/platforms/win32/vm/sqPlatformSpecific.h
===================================================================
--- branches/Cog/platforms/win32/vm/sqPlatformSpecific.h	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/win32/vm/sqPlatformSpecific.h	2013-01-31 01:42:03 UTC (rev 2676)
@@ -81,6 +81,8 @@
 extern void sqMakeMemoryNotExecutableFromTo(unsigned long, unsigned long);
 
 extern int isCFramePointerInUse(void);
+extern int osCogStackPageHeadroom(void);
+extern void reportMinimumUnusedHeadroom(void);
 #endif
 
 /* Thread support for thread-safe signalSemaphoreWithIndex and/or the COGMTVM */

Modified: branches/Cog/platforms/win32/vm/sqWin32Intel.c
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32Intel.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/win32/vm/sqWin32Intel.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -19,6 +19,7 @@
 #include <float.h>
 #include <ole2.h>
 #include "sq.h"
+#include "sqAssert.h"
 #include "sqWin32Backtrace.h"
 #include "sqSCCSVersion.h"
 #if COGVM
@@ -1017,6 +1018,11 @@
 sqInt
 ioExitWithErrorCode(int ec)
 {
+#if COGVM
+extern sqInt reportStackHeadroom;
+	if (reportStackHeadroom)
+		reportMinimumUnusedHeadroom();
+#endif
 	printPhaseTime(3);
 	inCleanExit = 1;
 	exit(ec);
@@ -1132,6 +1138,9 @@
   print_backtrace(stdout, nframes, MAXFRAMES, callstack, symbolic_pcs);
   /* print the caller's stack to stdout */
   dumpStackIfInMainThread(0);
+#if COGVM
+  reportMinimumUnusedHeadroom();
+#endif
 
   } EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
     /* that's too bad ... */
@@ -1679,6 +1688,10 @@
 		extern sqInt suppressHeartbeatFlag;
 		suppressHeartbeatFlag = 1;
 		return 1; }
+    else if (!strcmp(argv[0], "-reportheadroom")) { 
+		extern sqInt reportStackHeadroom;
+		reportStackHeadroom = 1;
+		return 1; }
 #endif /* STACKVM */
 #if COGVM
 	else if (!strcmp(argv[0], "-codesize")) { 
@@ -1895,11 +1908,16 @@
 }
 
 #if COGVM
+#include <signal.h>
+
 /*
  * Support code for Cog.
  * a) Answer whether the C frame pointer is in use, for capture of the C stack
  *    pointers.
+ * b) answer the amount of stack room to ensure in a Cog stack page, including
+ *    the size of the redzone, if any.
  */
+# if defined(i386) || defined(__i386) || defined(__i386__)
 /*
  * Cog has already captured CStackPointer  before calling this routine.  Record
  * the original value, capture the pointers again and determine if CFramePointer
@@ -1916,9 +1934,60 @@
 
 	currentCSP = CStackPointer;
 	ceCaptureCStackPointers();
-#if defined(assert)
 	assert(CStackPointer < currentCSP);
-#endif
 	return CFramePointer >= CStackPointer && CFramePointer <= currentCSP;
 }
+# endif /* defined(i386) || defined(__i386) || defined(__i386__) */
+
+/* Answer an approximation of the size of the redzone (if any).  Do so by
+ * sending a signal to the process and computing the difference between the
+ * stack pointer in the signal handler and that in the caller. Assumes stacks
+ * descend.
+ */
+
+#if !defined(min)
+# define min(x,y) (((x)>(y))?(y):(x))
+#endif
+static char *p = 0;
+
+static void
+sighandler(int sig) { p = (char *)&sig; }
+
+static int
+getRedzoneSize()
+{
+#if defined(SIGPROF) /* cygwin */
+	struct sigaction handler_action, old;
+	handler_action.sa_sigaction = sighandler;
+	handler_action.sa_flags = SA_NODEFER | SA_SIGINFO;
+	sigemptyset(&handler_action.sa_mask);
+	(void)sigaction(SIGPROF, &handler_action, &old);
+
+	do kill(getpid(),SIGPROF); while (!p);
+	(void)sigaction(SIGPROF, &old, 0);
+	return (char *)min(&old,&handler_action) - sizeof(struct sigaction) - p;
+#else /* cygwin */
+	void (*old)(int) = signal(SIGBREAK, sighandler);
+
+	do raise(SIGBREAK); while (!p);
+	return (char *)&old - p;
+#endif /* cygwin */
+}
+
+sqInt reportStackHeadroom;
+static int stackPageHeadroom;
+
+/* Answer the redzone size plus space for any signal handlers to run in.
+ * N.B. Space for signal handers may include space for the dynamic linker to
+ * run in since signal handlers may reference other functions, and linking may
+ * be lazy.  The reportheadroom switch can be used to check empirically that
+ * there is sufficient headroom.
+ */
+int
+osCogStackPageHeadroom()
+{
+	if (!stackPageHeadroom)
+		stackPageHeadroom = getRedzoneSize() + 1024;
+	return stackPageHeadroom;
+}
 #endif /* COGVM */

Modified: branches/Cog/platforms/win32/vm/sqWin32Window.c
===================================================================
--- branches/Cog/platforms/win32/vm/sqWin32Window.c	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/platforms/win32/vm/sqWin32Window.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -3203,6 +3203,7 @@
 				   TEXT("\n\t-stackpages: n \t(use n stack pages)")
                    TEXT("\n\t-numextsems: n \t(allow up to n external semaphores)")
                    TEXT("\n\t-noheartbeat \t(no heartbeat for debug)")
+                   TEXT("\n\t-reportheadroom \t(print unused stack headroom on exit)")
 #endif /* STACKVM */
 #if STACKVM || NewspeakVM
 # if COGVM

Modified: branches/Cog/scripts/uploadvms
===================================================================
--- branches/Cog/scripts/uploadvms	2013-01-28 01:10:14 UTC (rev 2675)
+++ branches/Cog/scripts/uploadvms	2013-01-31 01:42:03 UTC (rev 2676)
@@ -90,10 +90,10 @@
 echo compiling ChangeHistory
 THEM="`ls README.* | sort -n -t. -k2 -r`"
 >ChangeHistory
-for r in $MEHT; do
+for r in $THEM; do
 	m="`echo $r | sed 's/README.//'`"
-	if [ $n -ge $m ]; then
-		test $n -ne $m && echo "-------------------------------" >>ChangeHistory
+	if [ $REV -ge $m ]; then
+		test $REV -ne $m && echo "-------------------------------" >>ChangeHistory
 		ls -lT $r | awk '{ print $6, $7, $9; }' >>ChangeHistory
 		if grep -s "^------------" $r >/dev/null; then
 			awk '{if (line>0) print};/^--------/ {line=1}' $r >>ChangeHistory

Added: branches/Cog/src/plugins/GdbARMPlugin/GdbARMPlugin.c
===================================================================
--- branches/Cog/src/plugins/GdbARMPlugin/GdbARMPlugin.c	                        (rev 0)
+++ branches/Cog/src/plugins/GdbARMPlugin/GdbARMPlugin.c	2013-01-31 01:42:03 UTC (rev 2676)
@@ -0,0 +1,534 @@
+/* Automatically generated from Squeak on {14 December 2012 . 1:58:09 pm} */
+
+static char __buildInfo[] = "Generated on {14 December 2012 . 1:58:09 pm}. Compiled on "__DATE__ ;
+
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Default EXPORT macro that does nothing (see comment in sq.h): */
+#define EXPORT(returnType) returnType
+
+/* Do not include the entire sq.h file but just those parts needed. */
+/*  The virtual machine proxy definition */
+#include "sqVirtualMachine.h"
+/* Configuration options */
+#include "sqConfig.h"
+/* Platform specific definitions */
+#include "sqPlatformSpecific.h"
+
+#define true 1
+#define false 0
+#define null 0  /* using 'null' because nil is predefined in Think C */
+#ifdef SQUEAK_BUILTIN_PLUGIN
+#undef EXPORT
+// was #undef EXPORT(returnType) but screws NorCroft cc
+#define EXPORT(returnType) static returnType
+#endif
+
+#include "GdbARMPlugin.h"
+#include "sqMemoryAccess.h"
+
+
+/*** Constants ***/
+#define BaseHeaderSize 4
+#define BytesPerOop 4
+#define BytesPerWord 4
+#define PrimErrBadReceiver 2
+#define PrimErrInappropriate 6
+#define PrimErrNoMemory 9
+
+
+/*** Function Prototypes ***/
+static void forceStopOnInterrupt(void);
+static VirtualMachine * getInterpreter(void);
+EXPORT(const char*) getModuleName(void);
+static sqInt halt(void);
+static sqInt msg(char *s);
+EXPORT(sqInt) primitiveDisassembleAtInMemory(void);
+EXPORT(sqInt) primitiveErrorAndLog(void);
+EXPORT(sqInt) primitiveFlushICacheFromTo(void);
+EXPORT(sqInt) primitiveNewCPU(void);
+EXPORT(sqInt) primitiveResetCPU(void);
+EXPORT(sqInt) primitiveRunInMemoryMinimumAddressReadWrite(void);
+EXPORT(sqInt) primitiveSingleStepInMemoryMinimumAddressReadWrite(void);
+EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
+static sqInt sizeField(sqInt rcvr);
+static void sqAssert(sqInt aBool);
+static sqInt startOfData(sqInt rcvr);
+
+
+/*** Variables ***/
+
+#if !defined(SQUEAK_BUILTIN_PLUGIN)
+static void * (*arrayValueOf)(sqInt oop);
+static sqInt (*byteSizeOf)(sqInt oop);
+static sqInt (*classArray)(void);
+static sqInt (*classString)(void);
+static sqInt (*failed)(void);
+static void * (*firstIndexableField)(sqInt oop);
+static sqInt (*getInterruptPending)(void);
+static sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size);
+static sqInt (*integerObjectOf)(sqInt value);
+static sqInt (*isWordsOrBytes)(sqInt oop);
+static sqInt (*pop)(sqInt nItems);
+static sqInt (*popthenPush)(sqInt nItems, sqInt oop);
+static sqInt (*popRemappableOop)(void);
+static sqInt (*positive32BitIntegerFor)(sqInt integerValue);
+static sqInt (*positive32BitValueOf)(sqInt oop);
+static sqInt (*primitiveFail)(void);
+static sqInt (*primitiveFailFor)(sqInt reasonCode);
+static sqInt (*pushRemappableOop)(sqInt oop);
+static void (*(*setInterruptCheckChain)(void (*aFunction)(void)))() ;
+static sqInt (*stackValue)(sqInt offset);
+static sqInt (*storePointerofObjectwithValue)(sqInt index, sqInt oop, sqInt valuePointer);
+static sqInt (*success)(sqInt aBoolean);
+#else /* !defined(SQUEAK_BUILTIN_PLUGIN) */
+extern void * arrayValueOf(sqInt oop);
+extern sqInt byteSizeOf(sqInt oop);
+extern sqInt classArray(void);
+extern sqInt classString(void);
+extern sqInt failed(void);
+extern void * firstIndexableField(sqInt oop);
+extern sqInt getInterruptPending(void);
+extern sqInt instantiateClassindexableSize(sqInt classPointer, sqInt size);
+extern sqInt integerObjectOf(sqInt value);
+extern sqInt isWordsOrBytes(sqInt oop);
+extern sqInt pop(sqInt nItems);
+extern sqInt popthenPush(sqInt nItems, sqInt oop);
+extern sqInt popRemappableOop(void);
+extern sqInt positive32BitIntegerFor(sqInt integerValue);
+extern sqInt positive32BitValueOf(sqInt oop);
+extern sqInt primitiveFail(void);
+extern sqInt primitiveFailFor(sqInt reasonCode);
+extern sqInt pushRemappableOop(sqInt oop);
+extern void (*setInterruptCheckChain(void (*aFunction)(void)))() ;
+extern sqInt stackValue(sqInt offset);
+extern sqInt storePointerofObjectwithValue(sqInt index, sqInt oop, sqInt valuePointer);
+extern sqInt success(sqInt aBoolean);
+
+extern
+#endif
+struct VirtualMachine* interpreterProxy;
+static const char *moduleName =
+#ifdef SQUEAK_BUILTIN_PLUGIN
+	"GdbARMPlugin 14 December 2012 (i)"
+#else
+	"GdbARMPlugin 14 December 2012 (e)"
+#endif
+;
+
+
+static void
+forceStopOnInterrupt(void)
+{
+	if (getInterruptPending()) {
+		forceStopRunning();
+	}
+}
+
+
+/*	Note: This is coded so that plugins can be run from Squeak. */
+
+static VirtualMachine *
+getInterpreter(void)
+{
+	return interpreterProxy;
+}
+
+
+/*	Note: This is hardcoded so it can be run from Squeak.
+	The module name is used for validating a module *after*
+	it is loaded to check if it does really contain the module
+	we're thinking it contains. This is important! */
+
+EXPORT(const char*)
+getModuleName(void)
+{
+	return moduleName;
+}
+
+static sqInt
+halt(void)
+{
+	;
+	return 0;
+}
+
+static sqInt
+msg(char *s)
+{
+	fprintf(stderr, "\n%s: %s", moduleName, s);
+	return 0;
+}
+
+
+/*	cpuAlien <GdbARMAlien> */
+/*	<Integer> */
+/*	<Bitmap|ByteArray|WordArray> */
+/*	Return an Array of the instruction length and its decompilation as a
+	string for the instruction at address in memory.
+ */
+
+EXPORT(sqInt)
+primitiveDisassembleAtInMemory(void)
+{
+	unsigned long address;
+	void *cpu;
+	sqInt cpuAlien;
+	sqInt instrLenOrErr;
+	sqInt log;
+	sqInt logLen;
+	sqInt logObj;
+	sqInt logObjData;
+	char *memory;
+	sqInt resultObj;
+
+	address = positive32BitValueOf(stackValue(1));
+	success(isWordsOrBytes(stackValue(0)));
+	memory = ((char *) (firstIndexableField(stackValue(0))));
+	cpuAlien = stackValue(2);
+	if (failed()) {
+		return null;
+	}
+	if (((cpu = ((longAt(cpuAlien + BaseHeaderSize)) > 0
+	? (cpuAlien + BaseHeaderSize) + BytesPerOop
+	: longAt((cpuAlien + BaseHeaderSize) + BytesPerOop)))) == 0) {
+		primitiveFailFor(PrimErrBadReceiver);
+		return null;
+	}
+	instrLenOrErr = disassembleForAtInSize(cpu, address, memory, byteSizeOf(((sqInt)(long)(memory) - 4)));
+	if (instrLenOrErr < 0) {
+		primitiveFailFor(PrimErrInappropriate);
+		return null;
+	}
+	log = getlog((&logLen));
+	resultObj = instantiateClassindexableSize(classArray(), 2);
+	if (resultObj == 0) {
+		primitiveFailFor(PrimErrNoMemory);
+		return null;
+	}
+	pushRemappableOop(resultObj);
+	logObj = instantiateClassindexableSize(classString(), logLen);
+	if (failed()) {
+		popRemappableOop();
+		primitiveFailFor(PrimErrNoMemory);
+		return null;
+	}
+	logObjData = arrayValueOf(logObj);
+	memcpy(logObjData, log, logLen);
+	resultObj = popRemappableOop();
+	storePointerofObjectwithValue(0, resultObj, integerObjectOf(instrLenOrErr));
+	storePointerofObjectwithValue(1, resultObj, logObj);
+	if (failed()) {
+		return null;
+	}
+	popthenPush(3, resultObj);
+	return null;
+}
+
+EXPORT(sqInt)
+primitiveErrorAndLog(void)
+{
+	char *log;
+	sqInt logLen;
+	sqInt logObj;
+	char *logObjData;
+	sqInt resultObj;
+
+	log = getlog((&logLen));
+	resultObj = instantiateClassindexableSize(classArray(), 2);
+	if (resultObj == 0) {
+		primitiveFailFor(PrimErrNoMemory);
+		return null;
+	}
+	storePointerofObjectwithValue(0, resultObj, integerObjectOf(errorAcorn()));
+	if (logLen > 0) {
+		pushRemappableOop(resultObj);
+		logObj = instantiateClassindexableSize(classString(), logLen);
+		if (failed()) {
+			popRemappableOop();
+			primitiveFailFor(PrimErrNoMemory);
+			return null;
+		}
+		resultObj = popRemappableOop();
+		logObjData = arrayValueOf(logObj);
+		memcpy(logObjData, log, logLen);
+		storePointerofObjectwithValue(1, resultObj, logObj);
+	}
+	popthenPush(1, resultObj);
+	if (failed()) {
+		return null;
+	}
+	return null;
+}
+
+
+/*	cpuAlien <GdbARMAlien> */
+/*	<Integer> */
+/*	<Integer> */
+/*	Flush the icache in the requested range */
+
+EXPORT(sqInt)
+primitiveFlushICacheFromTo(void)
+{
+	void *cpu;
+	sqInt cpuAlien;
+	unsigned long endAddress;
+	unsigned long startAddress;
+
+	startAddress = positive32BitValueOf(stackValue(1));
+	endAddress = positive32BitValueOf(stackValue(0));
+	cpuAlien = stackValue(2);
+	if (failed()) {
+		return null;
+	}
+	if (((cpu = ((longAt(cpuAlien + BaseHeaderSize)) > 0
+	? (cpuAlien + BaseHeaderSize) + BytesPerOop
+	: longAt((cpuAlien + BaseHeaderSize) + BytesPerOop)))) == 0) {
+		primitiveFailFor(PrimErrBadReceiver);
+		return null;
+	}

@@ Diff output truncated at 50000 characters. @@


More information about the Vm-dev mailing list