[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