[Vm-dev] [commit] r2413 - Merging support files from cogvm branch.

commits at squeakvm.org commits at squeakvm.org
Thu Jun 9 08:29:00 UTC 2011


Author: andreas
Date: 2011-06-09 01:29:00 -0700 (Thu, 09 Jun 2011)
New Revision: 2413

Modified:
   trunk/platforms/Cross/plugins/IA32ABI/dabusiness.h
   trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h
   trunk/platforms/Cross/plugins/IA32ABI/ia32abicc.c
Log:
Merging support files from cogvm branch.

Modified: trunk/platforms/Cross/plugins/IA32ABI/dabusiness.h
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/dabusiness.h	2011-06-09 08:26:25 UTC (rev 2412)
+++ trunk/platforms/Cross/plugins/IA32ABI/dabusiness.h	2011-06-09 08:29:00 UTC (rev 2413)
@@ -1,16 +1,13 @@
 /*
- * Copyright 2008 Cadence Design Systems, Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the ''License''); you may not use this file except in compliance with the License.  You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0
- */
-/*
  *  dabusiness.h
  *
  *  Written by Eliot Miranda 11/07.
- *  Parts written by John M McIntosh 12/08
+ *	Updated 5/2011 to cope with Cog stack direction.
  *
  * Body of the various callIA32XXXReturn functions.
  * Call a foreign function according to IA32-ish ABI rules.
+ * N.B. In Cog Stack and Cogit VMs numArgs is negative to access args from
+ * the downward-growing stack.
  */
 	long i, size;
 	sqInt funcAlien, resultMaybeAlien;
@@ -19,23 +16,23 @@
 	char *argstart;
 #endif
 
-	/* For macintel we can ignore the typearray */ 
-
-	EnsureHaveVMThreadID();
-
+#if STACKVM /* Need to access args downwards from first arg */
+  if (numArgs < 0)
+	for (i = size = 0; --i > numArgs;) {
+		sqInt arg = argVector[i];
+		if (objIsAlien(arg) && sizeField(arg))
+			size += moduloPOT(sizeof(long),abs(sizeField(arg)));
+		else /* assume an integer or pointer.  check below. */
+			size += sizeof(long);
+	}
+  else
+#endif /* STACKVM */
 	for (i = numArgs, size = 0; --i >= 0;) {
 		sqInt arg = argVector[i];
 		if (objIsAlien(arg) && sizeField(arg))
 			size += moduloPOT(sizeof(long),abs(sizeField(arg)));
-		else /* assume an integer,double or pointer.  check below. */
-			if (interpreterProxy->isFloatObject(arg)) {
-				if (hasTypeArray) 
-					size += figureOutFloatSize(typeSignatureArray,i);
-				else
-					size += sizeof(double);
-			}
-			else
-				size += sizeof(long);
+		else /* assume an integer or pointer.  check below. */
+			size += sizeof(long);
 	}
 
 #if STACK_ALIGN_BYTES
@@ -54,11 +51,13 @@
 	 * %esp + 4, so the outgoing stack is offset by one word if uncorrected.
 	 * Grab the actual stack pointer to correct.
 	 */
-	getsp(argvec);
+	argvec = getsp();
 # endif
 #endif
 
-	for (i = 0; i < numArgs; i++) {
+#if STACKVM /* Need to access args downwards from first arg */
+  if (numArgs < 0)
+	for (i = size = 0; --i > numArgs;) {
 		sqInt arg = argVector[i];
 		if (isSmallInt(arg)) {
 			*(long *)argvec = intVal(arg);
@@ -81,25 +80,51 @@
 			argvec += sizeof(long);
 		}
 		else {
-			if (interpreterProxy->isFloatObject(arg)) {
-				double v = interpreterProxy->floatValueOf(arg);
+			long v = interpreterProxy->signed32BitValueOf(arg);
+			if (interpreterProxy->failed()) {
+				interpreterProxy->primitiveFailFor(0);
+				v = interpreterProxy->positive32BitValueOf(arg);
 				if (interpreterProxy->failed())
 					return PrimErrBadArgument;
-				if (hasTypeArray && figureOutFloatSize(typeSignatureArray,i) == sizeof(float)) {
-					float floatv = v;
-					*(float *)argvec = floatv;
-					argvec += sizeof(float);			
-				} else {
-					*(double *)argvec = v;
-					argvec += sizeof(double);			
-				}
-			} else {
-				long v = interpreterProxy->signed32BitValueOf(arg);
+			}
+			*(long *)argvec = v;
+			argvec += sizeof(long);
+		}
+	}
+  else
+#endif /* STACKVM */
+	for (i = 0; i < numArgs; i++) {
+		sqInt arg = argVector[i];
+		if (isSmallInt(arg)) {
+			*(long *)argvec = intVal(arg);
+			argvec += sizeof(long);
+		}
+		else if (objIsAlien(arg)) {
+			long  argByteSize;
+
+			if (!(size = sizeField(arg)))
+				size = argByteSize = sizeof(void *);
+			else
+				argByteSize = abs(size);
+			memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
+			argvec += moduloPOT(sizeof(long), argByteSize);
+		}
+		else if (objIsUnsafeAlien(arg)) {
+			sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
+			void *v = interpreterProxy->firstIndexableField(bitsObj);
+			*(void **)argvec = v;
+			argvec += sizeof(long);
+		}
+		else {
+			long v = interpreterProxy->signed32BitValueOf(arg);
+			if (interpreterProxy->failed()) {
+				interpreterProxy->primitiveFailFor(0);
+				v = interpreterProxy->positive32BitValueOf(arg);
 				if (interpreterProxy->failed())
 					return PrimErrBadArgument;
-				*(long *)argvec = v;
-				argvec += sizeof(long);
 			}
+			*(long *)argvec = v;
+			argvec += sizeof(long);
 		}
 	}
 
@@ -110,3 +135,14 @@
 	setsp(argstart);
 #endif
 	r = f();
+	/* post call need to refresh stack pointer in case of call-back and GC. */
+	resultMaybeAlien = interpreterProxy->stackValue(resultOffset);
+	if (objIsAlien(resultMaybeAlien)) {
+		if (!(size = sizeField(resultMaybeAlien)))
+			size = sizeof(void *);
+		memcpy(startOfDataWithSize(resultMaybeAlien,size),
+				&r,
+				min((unsigned)abs(size), sizeof(r)));
+	}
+
+	return PrimNoErr;

Modified: trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h	2011-06-09 08:26:25 UTC (rev 2412)
+++ trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h	2011-06-09 08:29:00 UTC (rev 2413)
@@ -1,14 +1,10 @@
 /*
- * Copyright 2008 Cadence Design Systems, Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the ''License''); you may not use this file except in compliance with the License.  You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0
- */
-/*
  *  platforms/Cross/plugins/IA32ABI/ia32abi.h
  *
- *  Written by Eliot Miranda 11/07.
+ *  Written by Eliot Miranda 11/2007.
+ *	Updated 5/2011 to cope with Cog stack direction.
  *
- * Call foreign functons returning results in either %eax, %edx (Integral)
+ * Call foreign functions returning results in either %eax, %edx (Integral)
  * or %f0 (Float, Double).  
  *
  * The primitive will have signatures of the form
@@ -24,41 +20,23 @@
  *	functionAddress <Alien> primFFICallResult: result <Alien>
  *	  with: firstArg <Alien> ... with: lastArg <Alien>
  *		<primitive: 'primCallOutXXX' module: 'IA32ABI'>
+ *
+ * N.B. In Cog Stack and Cogit VMs numArgs is negative to access args from
+ * the downward-growing stack.
  */
 
 #define SIGNATURE	sqInt *argVector/* call args on stack or in array */, \
-					int numArgs,	/* arg count of function to call   */ \
+					int numArgs,	/* arg count of function to call (*) */ \
 					int funcOffset, /* stack offset of func Alien   */ \
-					int resultOffset,/* stack offset of result Alien */ \
-					int hasTypeArray, /* last parm value is type array of sizes to support floating point arguments for powerpc */ \
-					int typeSignatureArray /* type signature array or nil object, or nil */
+					int resultOffset/* stack offset of result Alien */
 
 extern sqInt callIA32IntegralReturn(SIGNATURE);
 extern sqInt callIA32FloatReturn   (SIGNATURE);
 extern sqInt callIA32DoubleReturn  (SIGNATURE);
 extern long  thunkEntry            (void *thunkp, long *stackp);
 extern void *allocateExecutablePage(long *pagesize);
+extern VMCallbackContext *getMostRecentCallbackContext(void);
 
-/*
- * Returning values from callbacks is done through a CallBackReturnSpec
- * which contains a type tag and values.  It is designed to be overlaid upon
- * an FFICallbackReturnProxy created at the Smalltalk level to return values.
- */
-typedef  struct {
-	long type;
-# define retint32  0
-# define retint64  1
-# define retdouble 2
-# define retstruct 3
-	long _pad; /* so no doubt that valflt64 & valint32 et al are at byte 8 */
-union {
-		long valint32;
-		struct { long low, high; } valint64;
-		double valflt64;
-		struct { void *addr; long size; } valstruct;
-	} rvs;
-} CallBackReturnSpec;
-
 /* Use the most minimal setjmp/longjmp pair available; no signal handling
  * wanted or necessary.
  */

Modified: trunk/platforms/Cross/plugins/IA32ABI/ia32abicc.c
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/ia32abicc.c	2011-06-09 08:26:25 UTC (rev 2412)
+++ trunk/platforms/Cross/plugins/IA32ABI/ia32abicc.c	2011-06-09 08:29:00 UTC (rev 2413)
@@ -1,31 +1,12 @@
-#if defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__)
-#else
 /*
- * Copyright 2008 Cadence Design Systems, Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the ''License''); you may not use this file except in compliance with the License.  You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0
- */
-/* 
  *  ia32abicc.c
  *
  * Support for Call-outs and Call-backs from the Plugin.
  *  Written by Eliot Miranda 11/07.
- * Changes by John M McIntosh 12/08.
- *
  */
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
 # include "windows.h" /* for GetSystemInfo & VirtualAlloc */
-extern int inIoProcessEvents;
-# define noteEnterCallback() (++inIoProcessEvents)
-# define noteExitCallback()  do { if (inIoProcessEvents) --inIoProcessEvents; } while (0)
-# if DEBUG
-DWORD vmThread = 0;
-#  define EnsureHaveVMThreadID() do { \
-						if (!vmThread) vmThread = GetCurrentThreadId(); \
-						} while (0)
-#  define CheckInVMThread() (vmThread == GetCurrentThreadId())
-# endif /* DEBUG */
 #elif __APPLE__ && __MACH__
 # include <sys/mman.h> /* for mprotect */
 # if OBJC_DEBUG /* define this to get debug info for struct objc_class et al */
@@ -37,37 +18,26 @@
 void setbaz(void *p) { baz = p; }
 void *getbaz() { return baz; }
 # endif
+# include <stdlib.h> /* for valloc */
+# include <sys/mman.h> /* for mprotect */
 #else
-# include <malloc.h> /* for valloc */
+# include <stdlib.h> /* for valloc */
 # include <sys/mman.h> /* for mprotect */
 #endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+
+#include <string.h> /* for memcpy et al */
+#include <setjmp.h>
+#include <stdio.h> /* for fprintf(stderr,...) */
+
+#include "vmCallback.h"
 #include "sqMemoryAccess.h"
 #include "sqVirtualMachine.h"
 #include "ia32abi.h"
 
-#include <setjmp.h>
-
 #if !defined(min)
 # define min(a,b) ((a) < (b) ? (a) : (b))
 #endif
 
-#if !defined(noteEnterCallback)
-# define noteEnterCallback() 0
-#endif
-#if !defined(noteExitCallback)
-# define noteExitCallback() 0
-#endif
-#if !defined(EnsureHaveVMThreadID)
-# define EnsureHaveVMThreadID() 0
-#endif
-#if !defined(CheckInVMThread)
-# define CheckInVMThread() 1
-#endif
-
 #ifdef SQUEAK_BUILTIN_PLUGIN
 extern
 #endif 
@@ -87,8 +57,8 @@
 # define alloca _alloca
 #endif
 #if __GNUC__
-# define setsp(sp) asm volatile ("movl %0,%%esp" : : "memory"(sp))
-# define getsp(sp) asm volatile ("movl %%esp,%0" : "=r"(sp) : )
+# define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp))
+# define getsp() ({ void *esp; asm volatile ("movl %%esp,%0" : "=r"(esp) : ); esp;})
 #endif
 #if __APPLE__ && __MACH__ && __i386__
 # define STACK_ALIGN_BYTES 16
@@ -98,7 +68,7 @@
 # define setsp(ignored) 0
 #endif
 
-#define moduloPOT(m,v) ((v)+(m)-1 & ~((m)-1))
+#define moduloPOT(m,v) (((v)+(m)-1) & ~((m)-1))
 #define alignModuloPOT(m,v) ((void *)moduloPOT(m,(unsigned long)(v)))
 
 #define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()))
@@ -124,17 +94,6 @@
 #define isSmallInt(oop) ((oop)&1)
 #define intVal(oop) (((long)(oop))>>1)
 
-int figureOutFloatSize(int typeSignatureArray,int index) {
-	int floatSize,objectSize;
-	char *floatSizePointer;
-	sqInt oops = interpreterProxy->stackValue(typeSignatureArray);
-	objectSize = interpreterProxy->stSizeOf(oops);
-	if (index >= objectSize) 
-		return sizeof(double);
-	floatSizePointer = interpreterProxy->firstIndexableField(oops);
-	floatSize = floatSizePointer[index];
-	return floatSize;
-}
 /*
  * Call a foreign function that answers an integral result in %eax (and
  * possibly %edx) according to IA32-ish ABI rules.
@@ -147,7 +106,6 @@
 long long (*f)(), r;
 #endif
 #include "dabusiness.h"
-#include "dabusinessPostLogic.h"
 }
 
 /*
@@ -157,7 +115,6 @@
 sqInt
 callIA32FloatReturn(SIGNATURE) { float (*f)(), r;
 #include "dabusiness.h"
-#include "dabusinessPostLogic.h"
 }
 
 /*
@@ -167,9 +124,29 @@
 sqInt
 callIA32DoubleReturn(SIGNATURE) { double (*f)(), r;
 #include "dabusiness.h"
-#include "dabusinessPostLogic.h"
 }
 
+/* Queueing order for callback returns.  To ensure that callback returns occur
+ * in LIFO order we provide mostRecentCallbackContext which is tested by the return
+ * primitive primReturnFromContextThrough.  In a threaded VM this will have to
+ * be thread-specific (as yet unimplemented).
+ */
+#if COGMTVM
+# error as yet unimplemented
+/* Test if need and allocate a thread-local variable index in
+ * allocateExecutablePage (low frequency operation).  Keep a per-thread
+ * mostRecentCallbackContext.
+ */
+#else
+static VMCallbackContext *mostRecentCallbackContext = 0;
+
+VMCallbackContext *
+getMostRecentCallbackContext() { return mostRecentCallbackContext; }
+
+# define getRMCC(t) mostRecentCallbackContext
+# define setRMCC(t) (mostRecentCallbackContext = (void *)(t))
+#endif
+
 /*
  * Entry-point for call-back thunks.  Args are thunk address and stack pointer,
  * where the stack pointer is pointing one word below the return address of the
@@ -182,8 +159,8 @@
  *		thunkp
  * esp->retpc (thunkEntry)
  *
- * Pushing the stack pointer twice is done to keep the stack alignment to 16
- * bytes, a requirement on Mac OS X, and harmless elsewhere.
+ * The stack pointer is pushed twice to keep the stack alignment to 16 bytes, a
+ * requirement on platforms using SSE2 such as Mac OS X, and harmless elsewhere.
  *
  * This function's roles are to use setjmp/longjmp to save the call point
  * and return to it, and to return any of the various values from the callback.
@@ -192,70 +169,70 @@
  * arguments, the function would take 8 arguments, the 6 register args as
  * longs, followed by the thunkp and stackp passed on the stack.  The register
  * args would get copied into a struct on the stack. A pointer to the struct
- * is then passed as the 3rd argument of sendInvokeCallbackStackRegistersJmpbuf
+ * is then passed as an element of the VMCallbackContext.
  */
 long
 thunkEntry(void *thunkp, long *stackp)
 {
-	jmp_buf trampoline;
-	volatile CallBackReturnSpec *rs;
+	VMCallbackContext vmcc;
+	VMCallbackContext *previousCallbackContext;
+	int flags, returnType;
 
-	if (sizeof(int) != sizeof(rs)) {
-		perror("setjmp cannot return a pointer; reimplement!\n");
-		exit(1);
+	if ((flags = interpreterProxy->ownVM(0)) < 0) {
+		fprintf(stderr,"Warning; callback failed to own the VM\n");
+		return -1;
 	}
-	if (!CheckInVMThread()) {
-		printf("NOT IN VM THREAD!\n");
-		perror("Not in VM thread!\n");
-		exit(666);
-	}
 
-	noteEnterCallback();
-	if (!(rs = (void *)setjmp(trampoline))) {
-		interpreterProxy->
-			sendInvokeCallbackStackRegistersJmpbuf(	(sqInt)thunkp,
-													(sqInt)(stackp + 2),
-													0,
-													(sqInt)&trampoline);
-		perror("Warning; callback failed to invoke\n");
-		return 0;
+	if (!(returnType = setjmp(vmcc.trampoline))) {
+		previousCallbackContext = getRMCC();
+		setRMCC(&vmcc);
+		vmcc.thunkp = thunkp;
+		vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */
+		vmcc.intregargsp = 0;
+		vmcc.floatregargsp = 0;
+		interpreterProxy->sendInvokeCallbackContext(&vmcc);
+		fprintf(stderr,"Warning; callback failed to invoke\n");
+		setRMCC(previousCallbackContext);
+		interpreterProxy->disownVM(flags);
+		return -1;
 	}
-	noteExitCallback();
+	setRMCC(previousCallbackContext);
+	interpreterProxy->disownVM(flags);
 
-	switch (rs->type) {
+	switch (returnType) {
 
-	case retint32:	return rs->rvs.valint32;
+	case retword:	return vmcc.rvs.valword;
 
-	case retint64: {
-		long vhigh = rs->rvs.valint64.high;
+	case retword64: {
+		long vhigh = vmcc.rvs.valleint64.high;
 #if _MSC_VER
 				_asm mov edx, dword ptr vhigh;
 #elif __GNUC__
 				asm("mov %0,%%edx" : : "m"(vhigh));
 #else
-# error need to load edx with rs->rvs.valint64.high on this compiler
+# error need to load edx with vmcc.rvs.valleint64.high on this compiler
 #endif
-				return rs->rvs.valint64.low;
+				return vmcc.rvs.valleint64.low;
 	}
 
 	case retdouble: {
-		double valflt64 = rs->rvs.valflt64;
+		double valflt64 = vmcc.rvs.valflt64;
 #if _MSC_VER
 				_asm fld qword ptr valflt64;
 #elif __GNUC__
 				asm("fldl %0" : : "m"(valflt64));
 #else
-# error need to load %f0 with rs->rvs.valflt64 on this compiler
+# error need to load %f0 with vmcc.rvs.valflt64 on this compiler
 #endif
 				return 0;
 	}
 
 	case retstruct:	memcpy( (void *)(stackp[1]),
-						rs->rvs.valstruct.addr,
-						rs->rvs.valstruct.size);
-				return stackp[1];
+							vmcc.rvs.valstruct.addr,
+							vmcc.rvs.valstruct.size);
+					return stackp[1];
 	}
-	perror("Warning; invalid callback return type\n");
+	fprintf(stderr,"Warning; invalid callback return type\n");
 	return 0;
 }
 
@@ -267,7 +244,7 @@
  * is some (possiby unitary) multiple of the pagesize.
  *
  * We assume the Smalltalk image code will manage subdividing the executable
- * page amongst thunks so there is no need to free these pages, sicne the image
+ * page amongst thunks so there is no need to free these pages, since the image
  * will recycle parts of the page for reclaimed thunks.
  */
 #if defined(_MSC_VER) || defined(__MINGW32__)
@@ -280,6 +257,9 @@
 	void *mem;
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
+#if !defined(MEM_TOP_DOWN)
+# define MEM_TOP_DOWN 0x100000
+#endif
 	if (!pagesize) {
 		SYSTEM_INFO	sysinf;
 
@@ -309,4 +289,3 @@
 #endif
 	return mem;
 }
-#endif



More information about the Vm-dev mailing list