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. @@
vm-dev@lists.squeakfoundation.org