Mercurial > projects > dwt-mac
view 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 |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * * Port to the D Programming language: * Jacob Carlborg <jacob.carlborg@gmail.com> *******************************************************************************/ module dwt.internal.c.callback; import dwt.internal.Callback; alias size_t SWT_PTR; struct CALLBACK_DATA { Callback callback; jmethodID methodID; Object object; bool isStatic; bool isArrayBased; int argCount; SWT_PTR errorResult; } bool USE_ASSEMBLER = false; version (X86) bool USE_ASSEMBLER = true; private { CALLBACK_DATA callbackData[MAX_CALLBACKS]; int callbackEnabled = 1; int callbackEntryCount = 0; int initialized = 0; } SWT_PTR callback(int index, ...); static if (USE_ASSEMBLER) { version (Win32){} else version (Win32_WCE){} else import tango.stdc.posix.sys.mman; ubyte* callbackCode = null; int CALLBACK_THUNK_SIZE = 64; } SWT_PTR Java_org_eclipse_swt_internal_Callback_bind (JNIEnv* env, jclass that, jobject callbackObject, jobject object, jstring method, jstring signature, jint argCount, jboolean isStatic, jboolean isArrayBased, SWT_PTR errorResult) { int i; jmethodID mid = null; jclass javaClass = that; const char* methodString = null; const char* sigString = null; if (jvm == null) (*env).GetJavaVM(env, &jvm); if (!initialized) { memset(&callbackData, 0, sizeof(callbackData)); initialized = 1; } if (method) methodString = cast(/*const*/char*) (*env).GetStringUTFChars(env, method, null); if (signature) sigString = cast(/*const*/char*) (*env).GetStringUTFChars(env, signature, null); if (object && methodString && sigString) { if (isStatic) { mid = (*env).GetStaticMethodID(env, object, methodString, sigString); } else { javaClass = (*env).GetObjectClass(env, object); mid = (*env).GetMethodID(env, javaClass, methodString, sigString); } } if (method && methodString) (*env).ReleaseStringUTFChars(env, method, methodString); if (signature && sigString) (*env).ReleaseStringUTFChars(env, signature, sigString); if (mid == 0) goto fail; for (i = 0; i < MAX_CALLBACKS; i++) { if (!callbackData[i].callback) { if ((callbackData[i].callback = (*env).NewGlobalRef(env, callbackObject)) == null) goto fail; if ((callbackData[i].object = (*env).NewGlobalRef(env, object)) == null) goto fail; callbackData[i].isStatic = isStatic; callbackData[i].isArrayBased = isArrayBased; callbackData[i].argCount = argCount; callbackData[i].errorResult = errorResult; callbackData[i].methodID = mid; static if (!USE_ASSEMBLER) return cast(SWT_PTR) fnx_array[argCount][i]; { int j = 0, k, pad = 0; ubyte* code; if (callbackCode == null) { version (Win32) { callbackCode = VirtualAlloc(null, CALLBACK_THUNK_SIZE * MAX_CALLBACKS, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (callbackCode == null) return 0; } else version (Win32_WCE) { callbackCode = VirtualAlloc(null, CALLBACK_THUNK_SIZE * MAX_CALLBACKS, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (callbackCode == null) return 0; } else { callbackCode = mmap(null, CALLBACK_THUNK_SIZE * MAX_CALLBACKS, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (callbackCode == MAP_FAILED) return 0; } } code = cast(ubyte*) (callbackCode + (i * CALLBACK_THUNK_SIZE)); //PUSH EBP - 1 byte code[j++] = 0x55; //MOV EBP,ESP - 2 bytes code[j++] = 0x8b; code[j++] = 0xec; version (darwin) { /* darwin calling conventions require that the stack be aligned on a 16-byte boundary. */ k = (argCount + 3) * sizeof(SWT_PTR); pad = ((k + 15) & ~15) - k; if (pad > 0) { //SUB ESP,pad - 3 bytes code[j++] = 0x83; code[j++] = 0xec; code[j++] = pad; } } // 3*argCount bytes for (k = (argCount + 1) * sizeof(SWT_PTR); k >= sizeof(SWT_PTR) * 2; k -= sizeof( SWT_PTR)) { //PUSH SS:[EBP+k] code[j++] = 0xff; code[j++] = 0x75; code[j++] = k; } if (i > 127) { //PUSH i - 5 bytes code[j++] = 0x68; code[j++] = ((i >> 0) & 0xFF); code[j++] = ((i >> 8) & 0xFF); code[j++] = ((i >> 16) & 0xFF); code[j++] = ((i >> 24) & 0xFF); } else { //PUSH i - 2 bytes code[j++] = 0x6a; code[j++] = i; } //MOV EAX callback - 1 + sizeof(SWT_PTR) bytes code[j++] = 0xb8; (cast(SWT_PTR*) &code[j])[0] = cast(SWT_PTR) &callback; j += sizeof(SWT_PTR); //CALL EAX - 2 bytes code[j++] = 0xff; code[j++] = 0xd0; //ADD ESP,(argCount + 1) * sizeof(SWT_PTR) - 3 bytes code[j++] = 0x83; code[j++] = 0xc4; version (darwin) code[j++] = cast(ubyte) (pad + ((argCount + 1) * sizeof( SWT_PTR))); else code[j++] = cast(ubyte) ((argCount + 1) * sizeof(SWT_PTR)); //POP EBP - 1 byte code[j++] = 0x5d; version (Win32) { // RETN argCount * sizeof(SWT_PTR) - 3 bytes code[j++] = 0xc2; code[j++] = cast(ubyte) (argCount * sizeof(SWT_PTR)); code[j++] = 0x00; } else version (Win32_WCE) { // RETN argCount * sizeof(SWT_PTR) - 3 bytes code[j++] = 0xc2; code[j++] = cast(ubyte) (argCount * sizeof(SWT_PTR)); code[j++] = 0x00; } else { // RETN - 1 byte code[j++] = 0xc3; } if (j > CALLBACK_THUNK_SIZE) { jclass errorClass = (*env).FindClass(env, "java/lang/Error"); (*env).ThrowNew(env, errorClass, "Callback thunk overflow"); } return cast(SWT_PTR) code; } } } fail: return 0; }