Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
顯示
檢視
拆分
統一
即時編輯器
隱藏空白變更
摺疊未變更行
關閉換行
比對精度
智能
語法
無
變更外觀
處理
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
Untitled diff
建立於
8 年前
差異永不過期
清除
匯出
分享
解釋
136 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
307 行
全部複製
138 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
305 行
全部複製
/*
/*
複製
已複製
複製
已複製
*
ia32abicc.c
*
x64win64
ia32abicc.c
*
*
複製
已複製
複製
已複製
* Support for Call-outs and Call-backs from the Plugin
.
* Support for Call-outs and Call-backs from the Plugin
on x86_64 on Windows
.
*
Written by Eliot Miranda 11/07.
*
here referred to as x64win64ABI
*/
*/
複製
已複製
複製
已複製
/* null if compiled on other than x
86
, to get around gnu make bugs or
/* null if compiled on other than x
64
, to get around gnu make bugs or
* misunderstandings on our part.
* misunderstandings on our part.
*/
*/
複製
已複製
複製
已複製
#if
i386|i486|i586|i686
#if
x86_64|x64|__x86_64|__x86_64__|_M_AMD64|_M_X64
#if defined(_MSC_VER) || defined(__MINGW32__)
#if defined(_MSC_VER) || defined(__MINGW32__)
# include "windows.h" /* for GetSystemInfo & VirtualAlloc */
# include "windows.h" /* for GetSystemInfo & VirtualAlloc */
複製
已複製
複製
已複製
#elif __APPLE__ && __MACH__
# include <sys/mman.h> /* for mprotect */
# if OBJC_DEBUG /* define this to get debug info for struct objc_class et al */
# include <objc/objc.h>
# include <objc/objc-class.h>
struct objc_class *baz;
void setbaz(void *p) { baz = p; }
void *getbaz() { return baz; }
# endif
# include <stdlib.h> /* for valloc */
# include <sys/mman.h> /* for mprotect */
#else
#else
複製
已複製
複製
已複製
# error Non windows should use the SystemV ABI, not the win64 ABI
#endif
# include <stdlib.h> /* for valloc */
# include <stdlib.h> /* for valloc */
複製
已複製
複製
已複製
# include <sys/mman.h> /* for mprotect */
#endif
#include <string.h> /* for memcpy et al */
#include <string.h> /* for memcpy et al */
#include <setjmp.h>
#include <setjmp.h>
#include <stdio.h> /* for fprintf(stderr,...) */
#include <stdio.h> /* for fprintf(stderr,...) */
#include "sqMemoryAccess.h"
#include "sqMemoryAccess.h"
#include "vmCallback.h"
#include "vmCallback.h"
#include "sqAssert.h"
#include "sqAssert.h"
#include "sqVirtualMachine.h"
#include "sqVirtualMachine.h"
#include "ia32abi.h"
#include "ia32abi.h"
#if !defined(min)
#if !defined(min)
# define min(a,b) ((a) < (b) ? (a) : (b))
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#endif
複製
已複製
複製
已複製
#define NUM_REG_ARGS 4
#ifdef SQUEAK_BUILTIN_PLUGIN
#ifdef SQUEAK_BUILTIN_PLUGIN
extern
extern
#endif
#endif
struct VirtualMachine* interpreterProxy;
struct VirtualMachine* interpreterProxy;
複製
已複製
複製
已複製
#ifdef _MSC_VER
# define alloca _alloca
#endif
#if __GNUC__
#if __GNUC__
複製
已複製
複製
已複製
# define setsp(sp) asm volatile ("mov
l
%0,%%
e
sp" : : "m"(sp))
# define setsp(sp) asm volatile ("mov
q
%0,%%
r
sp" : : "m"(sp))
# define getsp() ({ void *sp; asm volatile ("mov
l
%%
e
sp,%0" : "=r"(sp) : ); sp;})
# define getsp() ({ void *sp; asm volatile ("mov
q
%%
r
sp,%0" : "=r"(sp) : ); sp;})
#endif
#if __APPLE__ && __MACH__ && __i386__
# define STACK_ALIGN_BYTES 16
#elif __linux__ && __i386__
# define STACK_ALIGN_BYTES 16
#elif defined(_WIN32) && __SSE2__
/* using sse2 instructions requires 16-byte stack alignment but on win32 there's
* no guarantee that libraries preserve alignment so compensate on callback.
*/
# define STACK_ALIGN_HACK 1
# define STACK_ALIGN_BYTES 16
#endif
#endif
複製
已複製
複製
已複製
#define STACK_ALIGN_BYTES 32 /* 32 if a 256-bit argument is passed; 16 otherwise */
#if !defined(setsp)
#if !defined(setsp)
# define setsp(ignored) 0
# define setsp(ignored) 0
#endif
#endif
複製
已複製
複製
已複製
#define
moduloPOT(m,v)
(((
v)+(m)-
1) & ~((
m)-
1))
#define
RoundUpPowerOfTwo(value, modulus) \
#define alignModuloPOT(m,v) ((void *)moduloPOT(m,(unsigned long)(v)))
(((
value) + (modulus) -
1) & ~((
modulus) -
1))
#define IsAlignedPowerOfTwo(value, modulus) \
(((value) & ((modulus) - 1)) == 0)
#define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()))
#define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()))
#define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien()))
#define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien()))
複製
已複製
複製
已複製
#define sizeField(alien) (*(
long *)pointerForOop((sqInt)(alien) + BaseHeaderSize))
#define sizeField(alien) (*(
long
long *)pointerForOop((sqInt)(alien) + BaseHeaderSize))
#define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop)
#define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop)
複製
已複製
複製
已複製
#if 0 /* obsolete after adding pointer Aliens with size field == 0 */
# define isIndirectOrPointer(alien) (sizeField(alien) <= 0)
# define startOfData(alien) (isIndirectOrPointer(alien) \
? *(void **)dataPtr(alien) \
: (void *)dataPtr(alien))
#endif
#define isIndirect(alien) (sizeField(alien) < 0)
#define isIndirect(alien) (sizeField(alien) < 0)
#define startOfParameterData(alien) (isIndirect(alien) \
#define startOfParameterData(alien) (isIndirect(alien) \
? *(void **)dataPtr(alien) \
? *(void **)dataPtr(alien) \
已保存差異
原始文本
開啟檔案
/* * ia32abicc.c * * Support for Call-outs and Call-backs from the Plugin. * Written by Eliot Miranda 11/07. */ /* null if compiled on other than x86, to get around gnu make bugs or * misunderstandings on our part. */ #if i386|i486|i586|i686 #if defined(_MSC_VER) || defined(__MINGW32__) # include "windows.h" /* for GetSystemInfo & VirtualAlloc */ #elif __APPLE__ && __MACH__ # include <sys/mman.h> /* for mprotect */ # if OBJC_DEBUG /* define this to get debug info for struct objc_class et al */ # include <objc/objc.h> # include <objc/objc-class.h> struct objc_class *baz; void setbaz(void *p) { baz = p; } void *getbaz() { return baz; } # endif # include <stdlib.h> /* for valloc */ # include <sys/mman.h> /* for mprotect */ #else # include <stdlib.h> /* for valloc */ # include <sys/mman.h> /* for mprotect */ #endif #include <string.h> /* for memcpy et al */ #include <setjmp.h> #include <stdio.h> /* for fprintf(stderr,...) */ #include "sqMemoryAccess.h" #include "vmCallback.h" #include "sqAssert.h" #include "sqVirtualMachine.h" #include "ia32abi.h" #if !defined(min) # define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; #ifdef _MSC_VER # define alloca _alloca #endif #if __GNUC__ # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp)) # define getsp() ({ void *sp; asm volatile ("movl %%esp,%0" : "=r"(sp) : ); sp;}) #endif #if __APPLE__ && __MACH__ && __i386__ # define STACK_ALIGN_BYTES 16 #elif __linux__ && __i386__ # define STACK_ALIGN_BYTES 16 #elif defined(_WIN32) && __SSE2__ /* using sse2 instructions requires 16-byte stack alignment but on win32 there's * no guarantee that libraries preserve alignment so compensate on callback. */ # define STACK_ALIGN_HACK 1 # define STACK_ALIGN_BYTES 16 #endif #if !defined(setsp) # define setsp(ignored) 0 #endif #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())) #define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien())) #define sizeField(alien) (*(long *)pointerForOop((sqInt)(alien) + BaseHeaderSize)) #define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop) #if 0 /* obsolete after adding pointer Aliens with size field == 0 */ # define isIndirectOrPointer(alien) (sizeField(alien) <= 0) # define startOfData(alien) (isIndirectOrPointer(alien) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #endif #define isIndirect(alien) (sizeField(alien) < 0) #define startOfParameterData(alien) (isIndirect(alien) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isIndirectSize(size) ((size) < 0) #define startOfDataWithSize(alien,size) (isIndirectSize(size) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isSmallInt(oop) ((oop)&1) #define intVal(oop) (((long)(oop))>>1) /* * Call a foreign function that answers an integral result in %eax (and * possibly %edx) according to IA32-ish ABI rules. */ sqInt callIA32IntegralReturn(SIGNATURE) { #ifdef _MSC_VER __int64 (*f)(), r; #else long long (*f)(), r; #endif #include "dabusiness.h" } /* * Call a foreign function that answers a single-precision floating-point * result in %f0 according to IA32-ish ABI rules. */ sqInt callIA32FloatReturn(SIGNATURE) { float (*f)(), r; #include "dabusiness.h" } /* * Call a foreign function that answers a double-precision floating-point * result in %f0 according to IA32-ish ABI rules. */ sqInt callIA32DoubleReturn(SIGNATURE) { double (*f)(), r; #include "dabusiness.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. Note that in the threaded VM * this does not have to be thread-specific or locked since it is within the * bounds of the ownVM/disownVM pair. */ static VMCallbackContext *mostRecentCallbackContext = 0; VMCallbackContext * getMostRecentCallbackContext() { return mostRecentCallbackContext; } #define getRMCC(t) mostRecentCallbackContext #define setRMCC(t) (mostRecentCallbackContext = (void *)(t)) /* * 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 * thunk's callee, 4 bytes below the thunk's first argument. The stack is: * callback * arguments * retpc (thunk) <--\ * address of retpc-/ <--\ * address of address of ret pc-/ * thunkp * esp->retpc (thunkEntry) * * 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, to correct C stack pointer alignment if necessary (see * STACK_ALIGN_HACK), and to return any of the various values from the callback. * * Looking forward to support for x86-64, which typically has 6 register * 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 an element of the VMCallbackContext. */ long thunkEntry(void *thunkp, sqIntptr_t *stackp) { VMCallbackContext vmcc; VMCallbackContext *previousCallbackContext; int flags, returnType; #if STACK_ALIGN_HACK { void *sp = getsp(); int offset = (unsigned long)sp & (STACK_ALIGN_BYTES - 1); if (offset) { # if _MSC_VER _asm sub esp, dword ptr offset; # elif __GNUC__ asm("sub %0,%%esp" : : "m"(offset)); # else # error need to subtract offset from esp # endif sp = getsp(); assert(!((unsigned long)sp & (STACK_ALIGN_BYTES - 1))); } } #endif /* STACK_ALIGN_HACK */ if ((flags = interpreterProxy->ownVM(0)) < 0) { fprintf(stderr,"Warning; callback failed to own the VM\n"); return -1; } 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; } setRMCC(previousCallbackContext); interpreterProxy->disownVM(flags); switch (returnType) { case retword: return vmcc.rvs.valword; 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 vmcc.rvs.valleint64.high on this compiler #endif return vmcc.rvs.valleint64.low; } case retdouble: { 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 vmcc.rvs.valflt64 on this compiler #endif return 0; } case retstruct: memcpy( (void *)(stackp[1]), vmcc.rvs.valstruct.addr, vmcc.rvs.valstruct.size); return stackp[1]; } fprintf(stderr,"Warning; invalid callback return type\n"); return 0; } /* * Thunk allocation support. Since thunks must be executable and some OSs * may not provide default execute permission on memory returned by malloc * we must provide memory that is guaranteed to be executable. The abstraction * is to answer an Alien that references an executable piece of memory that * 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, since the image * will recycle parts of the page for reclaimed thunks. */ #if defined(_MSC_VER) || defined(__MINGW32__) static unsigned long pagesize = 0; #endif void * allocateExecutablePage(long *size) { void *mem; #if defined(_MSC_VER) || defined(__MINGW32__) #if !defined(MEM_TOP_DOWN) # define MEM_TOP_DOWN 0x100000 #endif if (!pagesize) { SYSTEM_INFO sysinf; GetSystemInfo(&sysinf); pagesize = sysinf.dwPageSize; } /* N.B. VirtualAlloc MEM_COMMIT initializes the memory returned to zero. */ mem = VirtualAlloc( 0, pagesize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if (mem) *size = pagesize; #else long pagesize = getpagesize(); if (!(mem = valloc(pagesize))) return 0; memset(mem, 0, pagesize); if (mprotect(mem, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { free(mem); return 0; } *size = pagesize; #endif return mem; } #endif /* i386|i486|i586|i686 */
更改後文本
開啟檔案
/* * x64win64ia32abicc.c * * Support for Call-outs and Call-backs from the Plugin on x86_64 on Windows. * here referred to as x64win64ABI */ /* null if compiled on other than x64, to get around gnu make bugs or * misunderstandings on our part. */ #if x86_64|x64|__x86_64|__x86_64__|_M_AMD64|_M_X64 #if defined(_MSC_VER) || defined(__MINGW32__) # include "windows.h" /* for GetSystemInfo & VirtualAlloc */ #else # error Non windows should use the SystemV ABI, not the win64 ABI #endif # include <stdlib.h> /* for valloc */ #include <string.h> /* for memcpy et al */ #include <setjmp.h> #include <stdio.h> /* for fprintf(stderr,...) */ #include "sqMemoryAccess.h" #include "vmCallback.h" #include "sqAssert.h" #include "sqVirtualMachine.h" #include "ia32abi.h" #if !defined(min) # define min(a,b) ((a) < (b) ? (a) : (b)) #endif #define NUM_REG_ARGS 4 #ifdef SQUEAK_BUILTIN_PLUGIN extern #endif struct VirtualMachine* interpreterProxy; #if __GNUC__ # define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp)) # define getsp() ({ void *sp; asm volatile ("movq %%rsp,%0" : "=r"(sp) : ); sp;}) #endif #define STACK_ALIGN_BYTES 32 /* 32 if a 256-bit argument is passed; 16 otherwise */ #if !defined(setsp) # define setsp(ignored) 0 #endif #define RoundUpPowerOfTwo(value, modulus) \ (((value) + (modulus) - 1) & ~((modulus) - 1)) #define IsAlignedPowerOfTwo(value, modulus) \ (((value) & ((modulus) - 1)) == 0) #define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien())) #define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien())) #define sizeField(alien) (*(long long *)pointerForOop((sqInt)(alien) + BaseHeaderSize)) #define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop) #define isIndirect(alien) (sizeField(alien) < 0) #define startOfParameterData(alien) (isIndirect(alien) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isIndirectSize(size) ((size) < 0) #define startOfDataWithSize(alien,size) (isIndirectSize(size) \ ? *(void **)dataPtr(alien) \ : (void *)dataPtr(alien)) #define isSmallInt(oop) (((oop)&7)==1) #define intVal(oop) (((long long)(oop))>>3) extern void loadFloatRegs(double,double,double,double); typedef union { long long i; double d; } int64_or_double; /* * Call a foreign function that answers an integral result in %rax * according to x64-ish ABI rules. */ sqInt callIA32IntegralReturn(SIGNATURE) { long long (*f0)(long long rcx, long long rdx, long long r8, long long r9); long long (*f1)(double xmm0, long long rdx, long long r8, long long r9); long long (*f2)(long long rcx, double xmm1, long long r8, long long r9); long long (*f3)(double xmm0, double xmm1, long long r8, long long r9); long long (*f4)(long long rcx, long long rdx, double xmm2, long long r9); long long (*f5)(double xmm0, long long rdx, double xmm2, long long r9); long long (*f6)(long long rcx, double xmm1, double xmm2, long long r9); long long (*f7)(double xmm0, double xmm1, double xmm2, long long r9); long long (*f8)(long long rcx, long long rdx, long long r8, double xmm3); long long (*f9)(double xmm0, long long rdx, long long r8, double xmm3); long long (*fA)(long long rcx, double xmm1, long long r8, double xmm3); long long (*fB)(double xmm0, double xmm1, long long r8, double xmm3); long long (*fC)(long long rcx, long long rdx, double xmm2, double xmm3); long long (*fD)(double xmm0, long long rdx, double xmm2, double xmm3); long long (*fE)(long long rcx, double xmm1, double xmm2, double xmm3); long long (*fF)(double xmm0, double xmm1, double xmm2, double xmm3); long long r; #include "dax64win64business.h" } /* * Call a foreign function that answers a single-precision floating-point * result in %xmm0 according to x64-ish ABI rules. */ sqInt callIA32FloatReturn(SIGNATURE) { float (*f0)(long long rcx, long long rdx, long long r8, long long r9); float (*f1)(double xmm0, long long rdx, long long r8, long long r9); float (*f2)(long long rcx, double xmm1, long long r8, long long r9); float (*f3)(double xmm0, double xmm1, long long r8, long long r9); float (*f4)(long long rcx, long long rdx, double xmm2, long long r9); float (*f5)(double xmm0, long long rdx, double xmm2, long long r9); float (*f6)(long long rcx, double xmm1, double xmm2, long long r9); float (*f7)(double xmm0, double xmm1, double xmm2, long long r9); float (*f8)(long long rcx, long long rdx, long long r8, double xmm3); float (*f9)(double xmm0, long long rdx, long long r8, double xmm3); float (*fA)(long long rcx, double xmm1, long long r8, double xmm3); float (*fB)(double xmm0, double xmm1, long long r8, double xmm3); float (*fC)(long long rcx, long long rdx, double xmm2, double xmm3); float (*fD)(double xmm0, long long rdx, double xmm2, double xmm3); float (*fE)(long long rcx, double xmm1, double xmm2, double xmm3); float (*fF)(double xmm0, double xmm1, double xmm2, double xmm3); float r; #include "dax64win64business.h" } /* * Call a foreign function that answers a double-precision floating-point * result in %xmm0 according to x64-ish ABI rules. */ sqInt callIA32DoubleReturn(SIGNATURE) { double (*f0)(long long rcx, long long rdx, long long r8, long long r9); double (*f1)(double xmm0, long long rdx, long long r8, long long r9); double (*f2)(long long rcx, double xmm1, long long r8, long long r9); double (*f3)(double xmm0, double xmm1, long long r8, long long r9); double (*f4)(long long rcx, long long rdx, double xmm2, long long r9); double (*f5)(double xmm0, long long rdx, double xmm2, long long r9); double (*f6)(long long rcx, double xmm1, double xmm2, long long r9); double (*f7)(double xmm0, double xmm1, double xmm2, long long r9); double (*f8)(long long rcx, long long rdx, long long r8, double xmm3); double (*f9)(double xmm0, long long rdx, long long r8, double xmm3); double (*fA)(long long rcx, double xmm1, long long r8, double xmm3); double (*fB)(double xmm0, double xmm1, long long r8, double xmm3); double (*fC)(long long rcx, long long rdx, double xmm2, double xmm3); double (*fD)(double xmm0, long long rdx, double xmm2, double xmm3); double (*fE)(long long rcx, double xmm1, double xmm2, double xmm3); double (*fF)(double xmm0, double xmm1, double xmm2, double xmm3); double r; #include "dax64win64business.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. Note that in the threaded VM * this does not have to be thread-specific or locked since it is within the * bounds of the ownVM/disownVM pair. */ static VMCallbackContext *mostRecentCallbackContext = 0; VMCallbackContext * getMostRecentCallbackContext() { return mostRecentCallbackContext; } #define getRMCC(t) mostRecentCallbackContext #define setRMCC(t) (mostRecentCallbackContext = (void *)(t)) /* * 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 * thunk's callee, 4 bytes below the thunk's first argument. The stack is: * callback * arguments * retpc (thunk) <--\ * address of retpc-/ <--\ * address of address of ret pc-/ * thunkp * space for saving 4 registers rcx,rdx,r8,r9 * rsp->retpc (thunkEntry) * * 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. * * To support x86-64, which has 4 register arguments (int or floating-point) * the function takes 6 arguments, the 4 register args as long longs, * followed by the thunkp and stackp passed on the stack. The register * args get copied into a struct on the stack. A pointer to the struct is then * passed as an element of the VMCallbackContext. */ long long thunkEntry(long long rcx, long long rdx, long long r8, long long r9, void *thunkp, sqIntptr_t *stackp) { VMCallbackContext vmcc; VMCallbackContext *previousCallbackContext; long long flags, returnType; long long intargs[4]; double fpargs[4]; intargs[0] = rcx; intargs[1] = rdx; intargs[2] = r8; intargs[3] = r9; extern void saveFloatRegsWin64(long long xmm0,long long xmm1,long long xmm2, long long xmm3,double *fpargs); /* fake passing long long args */ saveFloatRegsWin64(rcx,rdx,r8,r9,fpargs); /* the callee expects double parameters that it will retrieve thru registers */ if ((flags = interpreterProxy->ownVM(0)) < 0) { fprintf(stderr,"Warning; callback failed to own the VM\n"); return -1; } if (!(returnType = setjmp(vmcc.trampoline))) { previousCallbackContext = getRMCC(); setRMCC(&vmcc); vmcc.thunkp = thunkp; vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */ vmcc.intregargsp = intargs; vmcc.floatregargsp = fpargs; interpreterProxy->sendInvokeCallbackContext(&vmcc); fprintf(stderr,"Warning; callback failed to invoke\n"); setRMCC(previousCallbackContext); interpreterProxy->disownVM(flags); return -1; } setRMCC(previousCallbackContext); interpreterProxy->disownVM(flags); switch (returnType) { case retword: return vmcc.rvs.valword; case retword64: return (((unsigned long long)vmcc.rvs.valleint64.high) << 32) | (unsigned int)vmcc.rvs.valleint64.low; case retdouble: fakeReturnDouble( vmcc.rvs.valflt64 ); return 0; case retstruct: memcpy( (void *)(stackp[1]), vmcc.rvs.valstruct.addr, vmcc.rvs.valstruct.size); return stackp[1]; } fprintf(stderr,"Warning; invalid callback return type\n"); return 0; } /* * Thunk allocation support. Since thunks must be executable and some OSs * may not provide default execute permission on memory returned by malloc * we must provide memory that is guaranteed to be executable. The abstraction * is to answer an Alien that references an executable piece of memory that * 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, since the image * will recycle parts of the page for reclaimed thunks. */ #if defined(_MSC_VER) || defined(__MINGW32__) static unsigned long pagesize = 0; #endif void * allocateExecutablePage(long *size) { void *mem; #if defined(_MSC_VER) || defined(__MINGW32__) #if !defined(MEM_TOP_DOWN) # define MEM_TOP_DOWN 0x100000 #endif if (!pagesize) { SYSTEM_INFO sysinf; GetSystemInfo(&sysinf); pagesize = sysinf.dwPageSize; } /* N.B. VirtualAlloc MEM_COMMIT initializes the memory returned to zero. */ mem = VirtualAlloc( 0, pagesize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if (mem) *size = pagesize; #else long long pagesize = getpagesize(); if (!(mem = valloc(pagesize))) return 0; memset(mem, 0, pagesize); if (mprotect(mem, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { free(mem); return 0; } *size = pagesize; #endif return mem; } #endif /* x86_64|x64|__x86_64|__x86_64__ */
尋找差異