Mercurial > projects > dwt-mac
view dwt/internal/c/callback.d @ 13:f565d3a95c0a
Ported dwt.internal
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Fri, 22 Aug 2008 16:46:34 +0200 |
parents | a329f9c3d66d |
children | 2952d5604c0a |
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; /** * Callback implementation. */ import tango.stdc.string; import dwt.dwthelper.utils; import dwt.internal.Callback; /* Header */ const bool REDUCED_CALLBACKS = false; alias size_t SWT_PTR; version (Win32) { import tango.sys.win32.UserGdi; import tango.sys.win32.Types; alias LRESULT RETURN_TYPE; } else version (Win32_WCE) { import tango.sys.win32.UserGdi; import tango.sys.win32.Types; alias LRESULT RETURN_TYPE; } else alias SWT_PTR RETURN_TYPE; version (X86) const bool USE_ASSEMBLER = true; else const bool USE_ASSEMBLER = true; static if (REDUCED_CALLBACKS) const int MAX_CALLBACKS = 16; else static if (USE_ASSEMBLER) const int MAX_CALLBACKS = 256; else const int MAX_CALLBACKS = 128; const int MAX_ARGS = 12; struct CALLBACK_DATA { Callback callback; jmethodID methodID; Object object; bool isStatic; bool isArrayBased; int argCount; SWT_PTR errorResult; } /* Implementation */ /* --------------- callback globals ----------------- */ private { CALLBACK_DATA callbackData[MAX_CALLBACKS]; int callbackEnabled = 1; int callbackEntryCount = 0; bool initialized = 0; debug int counter = 0; } static if (USE_ASSEMBLER) { version (Win32){} else version (Win32_WCE){} else import tango.stdc.posix.sys.mman; private ubyte* callbackCode = null; const int CALLBACK_THUNK_SIZE = 64; } SWT_PTR bind (Callback callbackObject, Object object, String method, String signature, int argCount, bool isStatic, bool isArrayBased, SWT_PTR errorResult) { int i; jmethodID mid = null; jclass javaClass = that; string methodString = null; string sigString = null; if (!initialized) { memset(&callbackData, 0, callbackData.sizeof); initialized = true; } if (method) methodString = method; if (signature) sigString = signature; 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 (mid == 0) goto fail; for (i = 0; i < MAX_CALLBACKS; i++) { if (!callbackData[i].callback) { if ((callbackData[i].callback = callbackObject) == null) goto fail; if ((callbackData[i].object = 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]; else { 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) * SWT_PTR.sizeof; 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) * SWT_PTR.sizeof; k >= SWT_PTR.sizeof * 2; k -= SWT_PTR.sizeof) { //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 + SWT_PTR.sizeof bytes code[j++] = 0xb8; (cast(SWT_PTR*) &code[j])[0] = cast(SWT_PTR) &callback; j += SWT_PTR.sizeof; //CALL EAX - 2 bytes code[j++] = 0xff; code[j++] = 0xd0; //ADD ESP,(argCount + 1) * SWT_PTR.sizeof - 3 bytes code[j++] = 0x83; code[j++] = 0xc4; version (darwin) code[j++] = cast(ubyte) (pad + ((argCount + 1) * SWT_PTR.sizeof)); else code[j++] = cast(ubyte) ((argCount + 1) * SWT_PTR.sizeof); //POP EBP - 1 byte code[j++] = 0x5d; version (Win32) { // RETN argCount * SWT_PTR.sizeof - 3 bytes code[j++] = 0xc2; code[j++] = cast(ubyte) (argCount * SWT_PTR.sizeof); code[j++] = 0x00; } else version (Win32_WCE) { // RETN argCount * SWT_PTR.sizeof - 3 bytes code[j++] = 0xc2; code[j++] = cast(ubyte) (argCount * SWT_PTR.sizeof); code[j++] = 0x00; } else { // RETN - 1 byte code[j++] = 0xc3; } if (j > CALLBACK_THUNK_SIZE) throw new Error("Callback thunk overflow"); return cast(SWT_PTR) code; } } } fail: return 0; } void unbind (Callback callback) { int i; for (i=0; i<MAX_CALLBACKS; i++) { if (callbackData[i].callback !is null && callbackData[i].callback == callback) { if (callbackData[i].callback !is null) delete callbackData[i].callback; if (callbackData[i].object !is null) delete allbackData[i].object; memset(&callbackData[i], 0, CALLBACK_DATA.sizeof); } } } bool getEnabled () { return callbackEnabled; } int getEntryCount () { return callbackEntryCount; } void setEnabled (bool enable) { callbackEnabled = enable; } void reset () { memset(cast(void*) &callbackData, 0, callbackData.sizeof); }