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 |
Free forum by Nabble | Edit this page |