Diff
checker
Texto
Texto
Imagens
Documentos
Excel
Pastas
Legal
Enterprise
Aplicativo para desktop
Preços
Fazer login
Baixar o Diffchecker Desktop
Comparar texto
Encontre a diferença entre dois arquivos de texto
Ferramentas
Histórico
Editor live
Recolher inalteradas
Sem quebra de linha
Layout
Dividido
Unificado
Nível de detalhe
Inteligente
Palavra
Caractere
Realce de sintaxe
Escolher sintaxe
Ignorar
Transformar texto
Ir à primeira mudança
Editar entrada
Diffchecker Desktop
A maneira mais segura de usar o Diffchecker. Obtenha o aplicativo Diffchecker Desktop: seus diffs nunca saem do seu computador!
Obter Desktop
Untitled diff
Criado
há 8 anos
O diff nunca expira
Limpar
Exportar
Compartilhar
Explicar
136 remoções
Linhas
Total
Removido
Caracteres
Total
Removido
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
307 linhas
Copiar tudo
137 adições
Linhas
Total
Adicionado
Caracteres
Total
Adicionado
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
305 linhas
Copiar tudo
/*
/*
Copiar
Copiado
Copiar
Copiado
*
ia32abicc.c
*
x64win64
ia32abicc.c
*
*
Copiar
Copiado
Copiar
Copiado
* 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
*/
*/
Copiar
Copiado
Copiar
Copiado
/* 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.
*/
*/
Copiar
Copiado
Copiar
Copiado
#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 */
Copiar
Copiado
Copiar
Copiado
#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
Copiar
Copiado
Copiar
Copiado
# include <stdlib.h> /* for valloc */
# error Non windows should use the SystemV ABI, not the win64 ABI
# include <sys/mman.h> /* for mprotect */
#endif
#endif
Copiar
Copiado
Copiar
Copiado
# include <stdlib.h> /* for valloc */
#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
Copiar
Copiado
Copiar
Copiado
#define NUM_REG_ARGS 4
#ifdef SQUEAK_BUILTIN_PLUGIN
#ifdef SQUEAK_BUILTIN_PLUGIN
extern
extern
#endif
#endif
struct VirtualMachine* interpreterProxy;
struct VirtualMachine* interpreterProxy;
Copiar
Copiado
Copiar
Copiado
#ifdef _MSC_VER
# define alloca _alloca
#endif
#if __GNUC__
#if __GNUC__
Copiar
Copiado
Copiar
Copiado
# 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
Copiar
Copiado
Copiar
Copiado
#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
Copiar
Copiado
Copiar
Copiado
#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()))
Copiar
Copiado
Copiar
Copiado
#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)
Copiar
Copiado
Copiar
Copiado
#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) \
: (void *)dataPtr(alien))
: (void *)dataPtr(alien))
#define isIndirectSize(size) ((size) < 0)
#define isIndirectSize(size) ((size) < 0)
#define startOfDataWithSize(alien,size) (isIndirectSize(size) \
#define startOfDataWithSize(alien,size) (isIndirectSize(size) \
? *(void **)dataPtr(alien) \
? *(void **)dataPtr(alien) \
: (void *)dataPtr(alien))
: (void *)dataPtr(alien))
Copiar
Copiado
Copiar
Copiado
#define isSmallInt(oop) (
(oop)&
1)
#define isSmallInt(oop) (
(
(oop)&
7)==
1)
#define intVal(oop) (((long
)(oop))>>
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;
/*
/*
Copiar
Copiado
Copiar
Copiado
* Call a foreign function that answers an integral result in %
e
ax
(and
* Call a foreign function that answers an integral result in %
r
ax
*
possibly %edx)
according to
IA32
-ish ABI rules.
*
according to
x64
-ish ABI rules.
*/
*/
Copiar
Copiado
Copiar
Copiado
sqInt
sqInt
callIA32IntegralReturn(SIGNATURE) {
callIA32IntegralReturn(SIGNATURE) {
long long (*f0)(long long rcx, long long rdx, long long r8, long long r9);
#ifdef _MSC_VER
long long (*f1)(double xmm0, long long rdx, long long r8, long long r9);
__int64 (*f)(), r;
long long (*f2)(long long rcx, double xmm1, long long r8, long long r9);
#else
long long (*f3)(double xmm0, double xmm1, long long r8, long long r9);
long long (*f)(), r;
long long (*f4)(long long rcx, long long rdx, double xmm2, long long r9);
#endif
long long (*f5)(double xmm0, long long rdx, double xmm2, long long r9);
#include "da
business.h"
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 "dax64win64
business.h"
}
}
/*
/*
* Call a foreign function that answers a single-precision floating-point
* Call a foreign function that answers a single-precision floating-point
Copiar
Copiado
Copiar
Copiado
* result in %
f0
according to
IA32
-ish ABI rules.
* result in %
xmm0
according to
x64
-ish ABI rules.
*/
*/
Copiar
Copiado
Copiar
Copiado
sqInt
sqInt
callIA32FloatReturn(SIGNATURE) {
callIA32FloatReturn(SIGNATURE) {
float (*f)(), r;
float (*f0)(long long rcx, long long rdx, long long r8, long long r9);
#include "da
business.h"
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 "da
x64win64
business.h"
}
}
/*
/*
* Call a foreign function that answers a double-precision floating-point
* Call a foreign function that answers a double-precision floating-point
Copiar
Copiado
Copiar
Copiado
* result in %
f0
according to
IA32
-ish ABI rules.
* result in %
xmm0
according to
x64
-ish ABI rules.
*/
*/
Copiar
Copiado
Copiar
Copiado
sqInt
sqInt
callIA32DoubleReturn(SIGNATURE) {
callIA32DoubleReturn(SIGNATURE) {
double (*f)(), r;
double (*f0)(long long rcx, long long rdx, long long r8, long long r9);
#include "da
business.h"
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 "da
x64win64
business.h"
}
}
/* Queueing order for callback returns. To ensure that callback returns occur
/* Queueing order for callback returns. To ensure that callback returns occur
* in LIFO order we provide mostRecentCallbackContext which is tested by the
* in LIFO order we provide mostRecentCallbackContext which is tested by the
* return primitive primReturnFromContextThrough. Note that in the threaded VM
* return primitive primReturnFromContextThrough. Note that in the threaded VM
* this does not have to be thread-specific or locked since it is within the
* this does not have to be thread-specific or locked since it is within the
* bounds of the ownVM/disownVM pair.
* bounds of the ownVM/disownVM pair.
*/
*/
static VMCallbackContext *mostRecentCallbackContext = 0;
static VMCallbackContext *mostRecentCallbackContext = 0;
VMCallbackContext *
VMCallbackContext *
getMostRecentCallbackContext() { return mostRecentCallbackContext; }
getMostRecentCallbackContext() { return mostRecentCallbackContext; }
#define getRMCC(t) mostRecentCallbackContext
#define getRMCC(t) mostRecentCallbackContext
#define setRMCC(t) (mostRecentCallbackContext = (void *)(t))
#define setRMCC(t) (mostRecentCallbackContext = (void *)(t))
/*
/*
* Entry-point for call-back thunks. Args are thunk address and stack pointer,
* 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
* 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:
* thunk's callee, 4 bytes below the thunk's first argument. The stack is:
* callback
* callback
* arguments
* arguments
* retpc (thunk) <--\
* retpc (thunk) <--\
* address of retpc-/ <--\
* address of retpc-/ <--\
* address of address of ret pc-/
* address of address of ret pc-/
* thunkp
* thunkp
Copiar
Copiado
Copiar
Copiado
* esp->retpc (thunkEntry)
* space for saving 4 registers rcx,rdx,r8,r9
*
* rsp->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
* This function's roles are to use setjmp/longjmp to save the call point
Copiar
Copiado
Copiar
Copiado
* and return to it
, to correct C stack pointer alignment if necessary (see
* and return to it
, and to return any of the various values from the callback.
* STACK_ALIGN_HACK)
, and to return any of the various values from the callback.
*
*
Copiar
Copiado
Copiar
Copiado
*
Looking forward to
support
for
x86-64, which
typically
has
6
register
*
To
support
x86-64, which
has
4
register
arguments
(int or floating-point)
*
arguments
,
the function
would
take
8
arguments, the
6
register args as
*
the function
take
s 6
arguments, the
4
register args as
long
longs,
*
longs,
followed by the thunkp and stackp passed on the stack. The register
*
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
* args
get copied into a struct on the stack. A pointer to the struct
is then
*
is then
passed as an element of the VMCallbackContext.
*
passed as an element of the VMCallbackContext.
*/
*/
Copiar
Copiado
Copiar
Copiado
long
thunkEntry(
void *thunkp, sqIntptr_t *stackp)
long
long
thunkEntry(
long long rcx, long long rdx,
long long r8, long long r9,
void *thunkp, sqIntptr_t *stackp)
{
{
VMCallbackContext vmcc;
VMCallbackContext vmcc;
VMCallbackContext *previousCallbackContext;
VMCallbackContext *previousCallbackContext;
Copiar
Copiado
Copiar
Copiado
int
flags, returnType;
long long
flags, returnType;
long long intargs[4];
double fpargs[4];
Copiar
Copiado
Copiar
Copiado
#if STACK_ALIGN_HACK
intargs[0] = rcx;
{ void *sp = getsp();
intargs[1] = rdx;
int offset = (unsigned long)sp & (STACK_ALIGN_BYTES - 1);
intargs[2] = r8;
if (offset) {
intargs[3] = r9;
# if _MSC_VER
_asm sub esp, dword ptr offset;
extern void saveFloatRegsWin64(long long xmm0,long long xmm1,long long xmm2, long long xmm3,double *fpargs); /* fake passing long long args */
# elif __GNUC__
saveFloatRegsWin64(rcx,rdx,r8,r9,fpargs); /* the callee expects double parameters that it will retrieve thru registers */
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) {
if ((flags = interpreterProxy->ownVM(0)) < 0) {
fprintf(stderr,"Warning; callback failed to own the VM\n");
fprintf(stderr,"Warning; callback failed to own the VM\n");
return -1;
return -1;
}
}
if (!(returnType = setjmp(vmcc.trampoline))) {
if (!(returnType = setjmp(vmcc.trampoline))) {
previousCallbackContext = getRMCC();
previousCallbackContext = getRMCC();
setRMCC(&vmcc);
setRMCC(&vmcc);
vmcc.thunkp = thunkp;
vmcc.thunkp = thunkp;
vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */
vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */
Copiar
Copiado
Copiar
Copiado
vmcc.intregargsp =
0
;
vmcc.intregargsp =
intargs
;
vmcc.floatregargsp =
0
;
vmcc.floatregargsp =
fpargs
;
interpreterProxy->sendInvokeCallbackContext(&vmcc);
interpreterProxy->sendInvokeCallbackContext(&vmcc);
fprintf(stderr,"Warning; callback failed to invoke\n");
fprintf(stderr,"Warning; callback failed to invoke\n");
setRMCC(previousCallbackContext);
setRMCC(previousCallbackContext);
interpreterProxy->disownVM(flags);
interpreterProxy->disownVM(flags);
return -1;
return -1;
}
}
setRMCC(previousCallbackContext);
setRMCC(previousCallbackContext);
interpreterProxy->disownVM(flags);
interpreterProxy->disownVM(flags);
switch (returnType) {
switch (returnType) {
case retword: return vmcc.rvs.valword;
case retword: return vmcc.rvs.valword;
Copiar
Copiado
Copiar
Copiado
case retword64:
{
case retword64:
return (((unsigned
long
long)
vmcc.rvs.valleint64.high
) << 32) | (unsigned int)
vmcc.rvs.valleint64.low;
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;
}
Copiar
Copiado
Copiar
Copiado
case retdouble:
{
case retdouble:
double valflt64 = vmcc.rvs.valflt64;
fakeReturnDouble( vmcc.rvs.valflt64 );
#if _MSC_VER
return 0;
_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]),
case retstruct: memcpy( (void *)(stackp[1]),
vmcc.rvs.valstruct.addr,
vmcc.rvs.valstruct.addr,
vmcc.rvs.valstruct.size);
vmcc.rvs.valstruct.size);
return stackp[1];
return stackp[1];
}
}
fprintf(stderr,"Warning; invalid callback return type\n");
fprintf(stderr,"Warning; invalid callback return type\n");
return 0;
return 0;
}
}
/*
/*
* Thunk allocation support. Since thunks must be executable and some OSs
* Thunk allocation support. Since thunks must be executable and some OSs
* may not provide default execute permission on memory returned by malloc
* may not provide default execute permission on memory returned by malloc
* we must provide memory that is guaranteed to be executable. The abstraction
* 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 to answer an Alien that references an executable piece of memory that
* is some (possiby unitary) multiple of the pagesize.
* is some (possiby unitary) multiple of the pagesize.
*
*
* We assume the Smalltalk image code will manage subdividing the executable
* 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
* page amongst thunks so there is no need to free these pages, since the image
* will recycle parts of the page for reclaimed thunks.
* will recycle parts of the page for reclaimed thunks.
*/
*/
#if defined(_MSC_VER) || defined(__MINGW32__)
#if defined(_MSC_VER) || defined(__MINGW32__)
static unsigned long pagesize = 0;
static unsigned long pagesize = 0;
#endif
#endif
void *
void *
allocateExecutablePage(long *size)
allocateExecutablePage(long *size)
{
{
void *mem;
void *mem;
#if defined(_MSC_VER) || defined(__MINGW32__)
#if defined(_MSC_VER) || defined(__MINGW32__)
#if !defined(MEM_TOP_DOWN)
#if !defined(MEM_TOP_DOWN)
# define MEM_TOP_DOWN 0x100000
# define MEM_TOP_DOWN 0x100000
#endif
#endif
if (!pagesize) {
if (!pagesize) {
SYSTEM_INFO sysinf;
SYSTEM_INFO sysinf;
GetSystemInfo(&sysinf);
GetSystemInfo(&sysinf);
pagesize = sysinf.dwPageSize;
pagesize = sysinf.dwPageSize;
}
}
/* N.B. VirtualAlloc MEM_COMMIT initializes the memory returned to zero. */
/* N.B. VirtualAlloc MEM_COMMIT initializes the memory returned to zero. */
mem = VirtualAlloc( 0,
mem = VirtualAlloc( 0,
pagesize,
pagesize,
MEM_COMMIT | MEM_TOP_DOWN,
MEM_COMMIT | MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
PAGE_EXECUTE_READWRITE);
if (mem)
if (mem)
*size = pagesize;
*size = pagesize;
#else
#else
Copiar
Copiado
Copiar
Copiado
long
pagesize = getpagesize();
long
long
pagesize = getpagesize();
if (!(mem = valloc(pagesize)))
if (!(mem = valloc(pagesize)))
return 0;
return 0;
memset(mem, 0, pagesize);
memset(mem, 0, pagesize);
if (mprotect(mem, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
if (mprotect(mem, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
free(mem);
free(mem);
return 0;
return 0;
}
}
*size = pagesize;
*size = pagesize;
#endif
#endif
return mem;
return mem;
}
}
Copiar
Copiado
Copiar
Copiado
#endif /*
i386|i486|i586|i686
*/
#endif /*
x86_64|x64|__x86_64|__x86_64__
*/
Diferenças salvas
Texto original
Abrir arquivo
/* * 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 */
Texto alterado
Abrir arquivo
/* * 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__ */
Encontrar Diferença