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

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

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

commits-3
 
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