Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
Untitled diff
作成日
8 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
136 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
307 行
すべてコピー
137 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
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
コピー
コピー済み
コピー
コピー済み
# 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
コピー
コピー済み
コピー
コピー済み
# 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
コピー
コピー済み
コピー
コピー済み
#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) \
: (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))
コピー
コピー済み
コピー
コピー済み
#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;
/*
/*
コピー
コピー済み
コピー
コピー済み
* 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.
*/
*/
コピー
コピー済み
コピー
コピー済み
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
コピー
コピー済み
コピー
コピー済み
* result in %
f0
according to
IA32
-ish ABI rules.
* result in %
xmm0
according to
x64
-ish ABI rules.
*/
*/
コピー
コピー済み
コピー
コピー済み
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
コピー
コピー済み
コピー
コピー済み
* result in %
f0
according to
IA32
-ish ABI rules.
* result in %
xmm0
according to
x64
-ish ABI rules.
*/
*/
コピー
コピー済み
コピー
コピー済み
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
コピー
コピー済み
コピー
コピー済み
* 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
コピー
コピー済み
コピー
コピー済み
* 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.
*
*
コピー
コピー済み
コピー
コピー済み
*
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.
*/
*/
コピー
コピー済み
コピー
コピー済み
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;
コピー
コピー済み
コピー
コピー済み
int
flags, returnType;
long long
flags, returnType;
long long intargs[4];
double fpargs[4];
コピー
コピー済み
コピー
コピー済み
#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) */
コピー
コピー済み
コピー
コピー済み
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;
コピー
コピー済み
コピー
コピー済み
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;
}
コピー
コピー済み
コピー
コピー済み
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
コピー
コピー済み
コピー
コピー済み
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;
}
}
コピー
コピー済み
コピー
コピー済み
#endif /*
i386|i486|i586|i686
*/
#endif /*
x86_64|x64|__x86_64|__x86_64__
*/
保存された差分
原文
ファイルを開く
/* * 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__ */
違いを見つける