[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