comparison dwt/internal/c/callback.d @ 0:380af2bdd8e5

Upload of whole dwt tree
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sat, 09 Aug 2008 17:00:02 +0200
parents
children 8b48be5454ce
comparison
equal deleted inserted replaced
-1:000000000000 0:380af2bdd8e5
1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *
11 * Port to the D Programming language:
12 * Jacob Carlborg <jacob.carlborg@gmail.com>
13 *******************************************************************************/
14 module dwt.internal.c.callback;
15
16 import dwt.internal.Callback;
17
18 alias size_t SWT_PTR;
19
20 struct CALLBACK_DATA
21 {
22 Callback callback;
23 jmethodID methodID;
24 Object object;
25 bool isStatic;
26 bool isArrayBased;
27 int argCount;
28 SWT_PTR errorResult;
29 }
30
31 bool USE_ASSEMBLER = false;
32
33 version (X86)
34 bool USE_ASSEMBLER = true;
35
36 private
37 {
38 CALLBACK_DATA callbackData[MAX_CALLBACKS];
39 int callbackEnabled = 1;
40 int callbackEntryCount = 0;
41 int initialized = 0;
42 }
43
44
45 SWT_PTR callback(int index, ...);
46
47 static if (USE_ASSEMBLER)
48 {
49 version (Win32){}
50 else version (Win32_WCE){}
51 else
52 import tango.stdc.posix.sys.mman;
53
54 ubyte* callbackCode = null;
55 int CALLBACK_THUNK_SIZE = 64;
56 }
57
58 SWT_PTR Java_org_eclipse_swt_internal_Callback_bind (JNIEnv* env, jclass that,
59 jobject callbackObject, jobject object, jstring method,
60 jstring signature, jint argCount, jboolean isStatic,
61 jboolean isArrayBased, SWT_PTR errorResult)
62 {
63 int i;
64 jmethodID mid = null;
65 jclass javaClass = that;
66 const char* methodString = null;
67 const char* sigString = null;
68
69 if (jvm == null)
70 (*env).GetJavaVM(env, &jvm);
71
72 if (!initialized)
73 {
74 memset(&callbackData, 0, sizeof(callbackData));
75 initialized = 1;
76 }
77
78 if (method)
79 methodString = cast(/*const*/char*) (*env).GetStringUTFChars(env,
80 method, null);
81
82 if (signature)
83 sigString = cast(/*const*/char*) (*env).GetStringUTFChars(env,
84 signature, null);
85
86 if (object && methodString && sigString)
87 {
88 if (isStatic)
89 {
90 mid = (*env).GetStaticMethodID(env, object, methodString, sigString);
91 }
92 else
93 {
94 javaClass = (*env).GetObjectClass(env, object);
95 mid = (*env).GetMethodID(env, javaClass, methodString, sigString);
96 }
97 }
98
99 if (method && methodString)
100 (*env).ReleaseStringUTFChars(env, method, methodString);
101
102 if (signature && sigString)
103 (*env).ReleaseStringUTFChars(env, signature, sigString);
104
105 if (mid == 0)
106 goto fail;
107
108 for (i = 0; i < MAX_CALLBACKS; i++)
109 {
110 if (!callbackData[i].callback)
111 {
112 if ((callbackData[i].callback = (*env).NewGlobalRef(env,
113 callbackObject)) == null)
114 goto fail;
115
116 if ((callbackData[i].object = (*env).NewGlobalRef(env, object)) == null)
117 goto fail;
118
119 callbackData[i].isStatic = isStatic;
120 callbackData[i].isArrayBased = isArrayBased;
121 callbackData[i].argCount = argCount;
122 callbackData[i].errorResult = errorResult;
123 callbackData[i].methodID = mid;
124
125 static if (!USE_ASSEMBLER)
126 return cast(SWT_PTR) fnx_array[argCount][i];
127
128 {
129 int j = 0, k, pad = 0;
130 ubyte* code;
131
132 if (callbackCode == null)
133 {
134 version (Win32)
135 {
136 callbackCode = VirtualAlloc(null,
137 CALLBACK_THUNK_SIZE * MAX_CALLBACKS,
138 MEM_COMMIT, PAGE_EXECUTE_READWRITE);
139 if (callbackCode == null)
140 return 0;
141 }
142
143 else version (Win32_WCE)
144 {
145 callbackCode = VirtualAlloc(null,
146 CALLBACK_THUNK_SIZE * MAX_CALLBACKS,
147 MEM_COMMIT, PAGE_EXECUTE_READWRITE);
148 if (callbackCode == null)
149 return 0;
150 }
151
152 else
153 {
154 callbackCode = mmap(null,
155 CALLBACK_THUNK_SIZE * MAX_CALLBACKS,
156 PROT_EXEC | PROT_READ | PROT_WRITE,
157 MAP_PRIVATE | MAP_ANON, -1, 0);
158 if (callbackCode == MAP_FAILED)
159 return 0;
160 }
161 }
162 code = cast(ubyte*) (callbackCode + (i * CALLBACK_THUNK_SIZE));
163
164 //PUSH EBP - 1 byte
165 code[j++] = 0x55;
166
167 //MOV EBP,ESP - 2 bytes
168 code[j++] = 0x8b;
169 code[j++] = 0xec;
170
171 version (darwin)
172 {
173 /* darwin calling conventions require that the stack be aligned on a 16-byte boundary. */
174 k = (argCount + 3) * sizeof(SWT_PTR);
175 pad = ((k + 15) & ~15) - k;
176 if (pad > 0)
177 {
178 //SUB ESP,pad - 3 bytes
179 code[j++] = 0x83;
180 code[j++] = 0xec;
181 code[j++] = pad;
182 }
183 }
184
185 // 3*argCount bytes
186 for (k = (argCount + 1) * sizeof(SWT_PTR); k >= sizeof(SWT_PTR) * 2; k -= sizeof(
187 SWT_PTR))
188 {
189 //PUSH SS:[EBP+k]
190 code[j++] = 0xff;
191 code[j++] = 0x75;
192 code[j++] = k;
193 }
194
195 if (i > 127)
196 {
197 //PUSH i - 5 bytes
198 code[j++] = 0x68;
199 code[j++] = ((i >> 0) & 0xFF);
200 code[j++] = ((i >> 8) & 0xFF);
201 code[j++] = ((i >> 16) & 0xFF);
202 code[j++] = ((i >> 24) & 0xFF);
203 }
204 else
205 {
206 //PUSH i - 2 bytes
207 code[j++] = 0x6a;
208 code[j++] = i;
209 }
210
211 //MOV EAX callback - 1 + sizeof(SWT_PTR) bytes
212 code[j++] = 0xb8;
213 (cast(SWT_PTR*) &code[j])[0] = cast(SWT_PTR) &callback;
214 j += sizeof(SWT_PTR);
215
216 //CALL EAX - 2 bytes
217 code[j++] = 0xff;
218 code[j++] = 0xd0;
219
220 //ADD ESP,(argCount + 1) * sizeof(SWT_PTR) - 3 bytes
221 code[j++] = 0x83;
222 code[j++] = 0xc4;
223
224 version (darwin)
225 code[j++] = cast(ubyte) (pad + ((argCount + 1) * sizeof(
226 SWT_PTR)));
227 else
228 code[j++] = cast(ubyte) ((argCount + 1) * sizeof(SWT_PTR));
229
230 //POP EBP - 1 byte
231 code[j++] = 0x5d;
232
233 version (Win32)
234 {
235 // RETN argCount * sizeof(SWT_PTR) - 3 bytes
236 code[j++] = 0xc2;
237 code[j++] = cast(ubyte) (argCount * sizeof(SWT_PTR));
238 code[j++] = 0x00;
239 }
240
241 else version (Win32_WCE)
242 {
243 // RETN argCount * sizeof(SWT_PTR) - 3 bytes
244 code[j++] = 0xc2;
245 code[j++] = cast(ubyte) (argCount * sizeof(SWT_PTR));
246 code[j++] = 0x00;
247 }
248
249 else
250 {
251 // RETN - 1 byte
252 code[j++] = 0xc3;
253 }
254
255 if (j > CALLBACK_THUNK_SIZE)
256 {
257 jclass
258 errorClass = (*env).FindClass(env,
259 "java/lang/Error");
260 (*env).ThrowNew(env, errorClass, "Callback thunk overflow");
261 }
262
263 return cast(SWT_PTR) code;
264 }
265 }
266 }
267
268 fail:
269 return 0;
270 }