michael@0: /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: michael@0: typedef unsigned nsresult; michael@0: typedef unsigned uint32_t; michael@0: typedef unsigned nsXPCVariant; michael@0: michael@0: michael@0: #if defined(WIN32) michael@0: #define NS_IMETHOD virtual nsresult __stdcall michael@0: #define NS_IMETHODIMP nsresult __stdcall michael@0: #else michael@0: #define NS_IMETHOD virtual nsresult michael@0: #define NS_IMETHODIMP nsresult michael@0: #endif michael@0: michael@0: michael@0: class base{ michael@0: public: michael@0: NS_IMETHOD ignored() = 0; michael@0: }; michael@0: michael@0: class foo : public base { michael@0: public: michael@0: NS_IMETHOD callme1(int i, int j) = 0; michael@0: NS_IMETHOD callme2(int i, int j) = 0; michael@0: NS_IMETHOD callme3(int i, int j) = 0; michael@0: }; michael@0: michael@0: class bar : public foo{ michael@0: public: michael@0: NS_IMETHOD ignored(); michael@0: NS_IMETHOD callme1(int i, int j); michael@0: NS_IMETHOD callme2(int i, int j); michael@0: NS_IMETHOD callme3(int i, int j); michael@0: }; michael@0: michael@0: /* michael@0: class baz : public base { michael@0: public: michael@0: NS_IMETHOD ignored(); michael@0: NS_IMETHOD callme1(); michael@0: NS_IMETHOD callme2(); michael@0: NS_IMETHOD callme3(); michael@0: void setfoo(foo* f) {other = f;} michael@0: michael@0: foo* other; michael@0: }; michael@0: NS_IMETHODIMP baz::ignored(){return 0;} michael@0: */ michael@0: michael@0: NS_IMETHODIMP bar::ignored(){return 0;} michael@0: michael@0: NS_IMETHODIMP bar::callme1(int i, int j) michael@0: { michael@0: printf("called bar::callme1 with: %d %d\n", i, j); michael@0: return 5; michael@0: } michael@0: michael@0: NS_IMETHODIMP bar::callme2(int i, int j) michael@0: { michael@0: printf("called bar::callme2 with: %d %d\n", i, j); michael@0: return 5; michael@0: } michael@0: michael@0: NS_IMETHODIMP bar::callme3(int i, int j) michael@0: { michael@0: printf("called bar::callme3 with: %d %d\n", i, j); michael@0: return 5; michael@0: } michael@0: michael@0: void docall(foo* f, int i, int j){ michael@0: f->callme1(i, j); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: #if defined(WIN32) michael@0: michael@0: static uint32_t __stdcall michael@0: invoke_count_words(uint32_t paramCount, nsXPCVariant* s) michael@0: { michael@0: return paramCount; michael@0: } michael@0: michael@0: static void __stdcall michael@0: invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s) michael@0: { michael@0: for(uint32_t i = 0; i < paramCount; i++, d++, s++) michael@0: { michael@0: *((uint32_t*)d) = *((uint32_t*)s); michael@0: } michael@0: } michael@0: michael@0: static nsresult __stdcall michael@0: DoInvoke(void* that, uint32_t index, michael@0: uint32_t paramCount, nsXPCVariant* params) michael@0: { michael@0: __asm { michael@0: push params michael@0: push paramCount michael@0: call invoke_count_words // stdcall, result in eax michael@0: shl eax,2 // *= 4 michael@0: sub esp,eax // make space for params michael@0: mov edx,esp michael@0: push params michael@0: push paramCount michael@0: push edx michael@0: call invoke_copy_to_stack // stdcall michael@0: mov ecx,that // instance in ecx michael@0: push ecx // push this michael@0: mov edx,[ecx] // vtable in edx michael@0: mov eax,index michael@0: shl eax,2 // *= 4 michael@0: add edx,eax michael@0: call [edx] // stdcall, i.e. callee cleans up stack. michael@0: } michael@0: } michael@0: michael@0: #else michael@0: /***************************************************************************/ michael@0: // just Linux_x86 now. Add other later... michael@0: michael@0: static uint32_t michael@0: invoke_count_words(uint32_t paramCount, nsXPCVariant* s) michael@0: { michael@0: return paramCount; michael@0: } michael@0: michael@0: static void michael@0: invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s) michael@0: { michael@0: for(uint32_t i = 0; i < paramCount; i++, d++, s++) michael@0: { michael@0: *((uint32_t*)d) = *((uint32_t*)s); michael@0: } michael@0: } michael@0: michael@0: static nsresult michael@0: DoInvoke(void* that, uint32_t index, michael@0: uint32_t paramCount, nsXPCVariant* params) michael@0: { michael@0: uint32_t result; michael@0: void* fn_count = invoke_count_words; michael@0: void* fn_copy = invoke_copy_to_stack; michael@0: michael@0: __asm__ __volatile__( michael@0: "pushl %4\n\t" michael@0: "pushl %3\n\t" michael@0: "movl %5, %%eax\n\t" michael@0: "call *%%eax\n\t" /* count words */ michael@0: "addl $0x8, %%esp\n\t" michael@0: "shl $2, %%eax\n\t" /* *= 4 */ michael@0: "subl %%eax, %%esp\n\t" /* make room for params */ michael@0: "movl %%esp, %%edx\n\t" michael@0: "pushl %4\n\t" michael@0: "pushl %3\n\t" michael@0: "pushl %%edx\n\t" michael@0: "movl %6, %%eax\n\t" michael@0: "call *%%eax\n\t" /* copy params */ michael@0: "addl $0xc, %%esp\n\t" michael@0: "movl %1, %%ecx\n\t" michael@0: "pushl %%ecx\n\t" michael@0: "movl (%%ecx), %%edx\n\t" michael@0: "movl %2, %%eax\n\t" /* function index */ michael@0: "shl $2, %%eax\n\t" /* *= 4 */ michael@0: "addl $8, %%eax\n\t" /* += 8 */ michael@0: "addl %%eax, %%edx\n\t" michael@0: "call *(%%edx)\n\t" /* safe to not cleanup esp */ michael@0: "movl %%eax, %0" michael@0: : "=g" (result) /* %0 */ michael@0: : "g" (that), /* %1 */ michael@0: "g" (index), /* %2 */ michael@0: "g" (paramCount), /* %3 */ michael@0: "g" (params), /* %4 */ michael@0: "g" (fn_count), /* %5 */ michael@0: "g" (fn_copy) /* %6 */ michael@0: : "ax", "cx", "dx", "memory" michael@0: ); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: #endif michael@0: /***************************************************************************/ michael@0: michael@0: int main() michael@0: { michael@0: nsXPCVariant params1[2] = {1,2}; michael@0: nsXPCVariant params2[2] = {2,4}; michael@0: nsXPCVariant params3[2] = {3,6}; michael@0: michael@0: foo* a = new bar(); michael@0: michael@0: // printf("calling via C++...\n"); michael@0: // docall(a, 12, 24); michael@0: michael@0: printf("calling via ASM...\n"); michael@0: DoInvoke(a, 1, 2, params1); michael@0: DoInvoke(a, 2, 2, params2); michael@0: DoInvoke(a, 3, 2, params3); michael@0: michael@0: return 0; michael@0: }