xpcom/reflect/xptcall/src/md/test/invoke_test.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,207 @@
     1.4 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include <stdio.h>
    1.10 +
    1.11 +typedef unsigned nsresult;
    1.12 +typedef unsigned uint32_t;
    1.13 +typedef unsigned nsXPCVariant;
    1.14 +
    1.15 +
    1.16 +#if defined(WIN32)
    1.17 +#define NS_IMETHOD virtual nsresult __stdcall
    1.18 +#define NS_IMETHODIMP nsresult __stdcall
    1.19 +#else
    1.20 +#define NS_IMETHOD virtual nsresult
    1.21 +#define NS_IMETHODIMP nsresult
    1.22 +#endif
    1.23 +
    1.24 +
    1.25 +class base{
    1.26 +public:
    1.27 +  NS_IMETHOD ignored() = 0;
    1.28 +};
    1.29 +
    1.30 +class foo : public base {
    1.31 +public:
    1.32 +  NS_IMETHOD callme1(int i, int j) = 0;
    1.33 +  NS_IMETHOD callme2(int i, int j) = 0;
    1.34 +  NS_IMETHOD callme3(int i, int j) = 0;
    1.35 +};
    1.36 +
    1.37 +class bar : public foo{
    1.38 +public:
    1.39 +  NS_IMETHOD ignored();
    1.40 +  NS_IMETHOD callme1(int i, int j);
    1.41 +  NS_IMETHOD callme2(int i, int j);
    1.42 +  NS_IMETHOD callme3(int i, int j);
    1.43 +};
    1.44 +
    1.45 +/*
    1.46 +class baz : public base {
    1.47 +public:
    1.48 +  NS_IMETHOD ignored();
    1.49 +  NS_IMETHOD callme1();
    1.50 +  NS_IMETHOD callme2();
    1.51 +  NS_IMETHOD callme3();
    1.52 +  void setfoo(foo* f) {other = f;}
    1.53 +
    1.54 +  foo* other;
    1.55 +};
    1.56 +NS_IMETHODIMP baz::ignored(){return 0;}
    1.57 +*/
    1.58 +
    1.59 +NS_IMETHODIMP bar::ignored(){return 0;}
    1.60 +
    1.61 +NS_IMETHODIMP bar::callme1(int i, int j)
    1.62 +{
    1.63 +  printf("called bar::callme1 with: %d %d\n", i, j);
    1.64 +  return 5;
    1.65 +}
    1.66 +
    1.67 +NS_IMETHODIMP bar::callme2(int i, int j)
    1.68 +{
    1.69 +  printf("called bar::callme2 with: %d %d\n", i, j);
    1.70 +  return 5;
    1.71 +}
    1.72 +
    1.73 +NS_IMETHODIMP bar::callme3(int i, int j)
    1.74 +{
    1.75 +  printf("called bar::callme3 with: %d %d\n", i, j);
    1.76 +  return 5;
    1.77 +}
    1.78 +
    1.79 +void docall(foo* f, int i, int j){
    1.80 +  f->callme1(i, j); 
    1.81 +}
    1.82 +
    1.83 +/***************************************************************************/
    1.84 +#if defined(WIN32)
    1.85 +
    1.86 +static uint32_t __stdcall
    1.87 +invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
    1.88 +{
    1.89 +    return paramCount;
    1.90 +}    
    1.91 +
    1.92 +static void __stdcall
    1.93 +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
    1.94 +{
    1.95 +    for(uint32_t i = 0; i < paramCount; i++, d++, s++)
    1.96 +    {
    1.97 +        *((uint32_t*)d) = *((uint32_t*)s);
    1.98 +    }
    1.99 +}
   1.100 +
   1.101 +static nsresult __stdcall
   1.102 +DoInvoke(void* that, uint32_t index,
   1.103 +         uint32_t paramCount, nsXPCVariant* params)
   1.104 +{
   1.105 +    __asm {
   1.106 +        push    params
   1.107 +        push    paramCount
   1.108 +        call    invoke_count_words  // stdcall, result in eax
   1.109 +        shl     eax,2               // *= 4
   1.110 +        sub     esp,eax             // make space for params
   1.111 +        mov     edx,esp
   1.112 +        push    params
   1.113 +        push    paramCount
   1.114 +        push    edx
   1.115 +        call    invoke_copy_to_stack // stdcall
   1.116 +        mov     ecx,that            // instance in ecx
   1.117 +        push    ecx                 // push this
   1.118 +        mov     edx,[ecx]           // vtable in edx
   1.119 +        mov     eax,index
   1.120 +        shl     eax,2               // *= 4
   1.121 +        add     edx,eax
   1.122 +        call    [edx]               // stdcall, i.e. callee cleans up stack.
   1.123 +    }
   1.124 +}
   1.125 +
   1.126 +#else
   1.127 +/***************************************************************************/
   1.128 +// just Linux_x86 now. Add other later...
   1.129 +
   1.130 +static uint32_t 
   1.131 +invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
   1.132 +{
   1.133 +    return paramCount;
   1.134 +}    
   1.135 +
   1.136 +static void 
   1.137 +invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
   1.138 +{
   1.139 +    for(uint32_t i = 0; i < paramCount; i++, d++, s++)
   1.140 +    {
   1.141 +        *((uint32_t*)d) = *((uint32_t*)s);
   1.142 +    }
   1.143 +}
   1.144 +
   1.145 +static nsresult
   1.146 +DoInvoke(void* that, uint32_t index,
   1.147 +         uint32_t paramCount, nsXPCVariant* params)
   1.148 +{
   1.149 +    uint32_t result;
   1.150 +    void* fn_count = invoke_count_words;
   1.151 +    void* fn_copy = invoke_copy_to_stack;
   1.152 +
   1.153 + __asm__ __volatile__(
   1.154 +    "pushl %4\n\t"
   1.155 +    "pushl %3\n\t"
   1.156 +    "movl  %5, %%eax\n\t"
   1.157 +    "call  *%%eax\n\t"       /* count words */
   1.158 +    "addl  $0x8, %%esp\n\t"
   1.159 +    "shl   $2, %%eax\n\t"    /* *= 4 */
   1.160 +    "subl  %%eax, %%esp\n\t" /* make room for params */
   1.161 +    "movl  %%esp, %%edx\n\t"
   1.162 +    "pushl %4\n\t"
   1.163 +    "pushl %3\n\t"
   1.164 +    "pushl %%edx\n\t"
   1.165 +    "movl  %6, %%eax\n\t"
   1.166 +    "call  *%%eax\n\t"       /* copy params */
   1.167 +    "addl  $0xc, %%esp\n\t"
   1.168 +    "movl  %1, %%ecx\n\t"
   1.169 +    "pushl %%ecx\n\t"
   1.170 +    "movl  (%%ecx), %%edx\n\t"
   1.171 +    "movl  %2, %%eax\n\t"   /* function index */
   1.172 +    "shl   $2, %%eax\n\t"   /* *= 4 */
   1.173 +    "addl  $8, %%eax\n\t"   /* += 8 */
   1.174 +    "addl  %%eax, %%edx\n\t"
   1.175 +    "call  *(%%edx)\n\t"    /* safe to not cleanup esp */
   1.176 +    "movl  %%eax, %0"
   1.177 +    : "=g" (result)         /* %0 */
   1.178 +    : "g" (that),           /* %1 */
   1.179 +      "g" (index),          /* %2 */
   1.180 +      "g" (paramCount),     /* %3 */
   1.181 +      "g" (params),         /* %4 */
   1.182 +      "g" (fn_count),       /* %5 */
   1.183 +      "g" (fn_copy)         /* %6 */
   1.184 +    : "ax", "cx", "dx", "memory" 
   1.185 +    );
   1.186 +  
   1.187 +  return result;
   1.188 +}    
   1.189 +
   1.190 +#endif
   1.191 +/***************************************************************************/
   1.192 +
   1.193 +int main()
   1.194 +{
   1.195 +  nsXPCVariant params1[2] = {1,2};
   1.196 +  nsXPCVariant params2[2] = {2,4};
   1.197 +  nsXPCVariant params3[2] = {3,6};
   1.198 +
   1.199 +  foo* a = new bar();
   1.200 +
   1.201 +//  printf("calling via C++...\n");
   1.202 +//  docall(a, 12, 24);
   1.203 +
   1.204 +  printf("calling via ASM...\n");
   1.205 +  DoInvoke(a, 1, 2, params1);
   1.206 +  DoInvoke(a, 2, 2, params2);
   1.207 +  DoInvoke(a, 3, 2, params3);
   1.208 +
   1.209 +  return 0;
   1.210 +}

mercurial