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

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:3f3a64e0f7dd
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include <stdio.h>
7
8 typedef unsigned nsresult;
9 typedef unsigned uint32_t;
10 typedef unsigned nsXPCVariant;
11
12
13 #if defined(WIN32)
14 #define NS_IMETHOD virtual nsresult __stdcall
15 #define NS_IMETHODIMP nsresult __stdcall
16 #else
17 #define NS_IMETHOD virtual nsresult
18 #define NS_IMETHODIMP nsresult
19 #endif
20
21
22 class base{
23 public:
24 NS_IMETHOD ignored() = 0;
25 };
26
27 class foo : public base {
28 public:
29 NS_IMETHOD callme1(int i, int j) = 0;
30 NS_IMETHOD callme2(int i, int j) = 0;
31 NS_IMETHOD callme3(int i, int j) = 0;
32 };
33
34 class bar : public foo{
35 public:
36 NS_IMETHOD ignored();
37 NS_IMETHOD callme1(int i, int j);
38 NS_IMETHOD callme2(int i, int j);
39 NS_IMETHOD callme3(int i, int j);
40 };
41
42 /*
43 class baz : public base {
44 public:
45 NS_IMETHOD ignored();
46 NS_IMETHOD callme1();
47 NS_IMETHOD callme2();
48 NS_IMETHOD callme3();
49 void setfoo(foo* f) {other = f;}
50
51 foo* other;
52 };
53 NS_IMETHODIMP baz::ignored(){return 0;}
54 */
55
56 NS_IMETHODIMP bar::ignored(){return 0;}
57
58 NS_IMETHODIMP bar::callme1(int i, int j)
59 {
60 printf("called bar::callme1 with: %d %d\n", i, j);
61 return 5;
62 }
63
64 NS_IMETHODIMP bar::callme2(int i, int j)
65 {
66 printf("called bar::callme2 with: %d %d\n", i, j);
67 return 5;
68 }
69
70 NS_IMETHODIMP bar::callme3(int i, int j)
71 {
72 printf("called bar::callme3 with: %d %d\n", i, j);
73 return 5;
74 }
75
76 void docall(foo* f, int i, int j){
77 f->callme1(i, j);
78 }
79
80 /***************************************************************************/
81 #if defined(WIN32)
82
83 static uint32_t __stdcall
84 invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
85 {
86 return paramCount;
87 }
88
89 static void __stdcall
90 invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
91 {
92 for(uint32_t i = 0; i < paramCount; i++, d++, s++)
93 {
94 *((uint32_t*)d) = *((uint32_t*)s);
95 }
96 }
97
98 static nsresult __stdcall
99 DoInvoke(void* that, uint32_t index,
100 uint32_t paramCount, nsXPCVariant* params)
101 {
102 __asm {
103 push params
104 push paramCount
105 call invoke_count_words // stdcall, result in eax
106 shl eax,2 // *= 4
107 sub esp,eax // make space for params
108 mov edx,esp
109 push params
110 push paramCount
111 push edx
112 call invoke_copy_to_stack // stdcall
113 mov ecx,that // instance in ecx
114 push ecx // push this
115 mov edx,[ecx] // vtable in edx
116 mov eax,index
117 shl eax,2 // *= 4
118 add edx,eax
119 call [edx] // stdcall, i.e. callee cleans up stack.
120 }
121 }
122
123 #else
124 /***************************************************************************/
125 // just Linux_x86 now. Add other later...
126
127 static uint32_t
128 invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
129 {
130 return paramCount;
131 }
132
133 static void
134 invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
135 {
136 for(uint32_t i = 0; i < paramCount; i++, d++, s++)
137 {
138 *((uint32_t*)d) = *((uint32_t*)s);
139 }
140 }
141
142 static nsresult
143 DoInvoke(void* that, uint32_t index,
144 uint32_t paramCount, nsXPCVariant* params)
145 {
146 uint32_t result;
147 void* fn_count = invoke_count_words;
148 void* fn_copy = invoke_copy_to_stack;
149
150 __asm__ __volatile__(
151 "pushl %4\n\t"
152 "pushl %3\n\t"
153 "movl %5, %%eax\n\t"
154 "call *%%eax\n\t" /* count words */
155 "addl $0x8, %%esp\n\t"
156 "shl $2, %%eax\n\t" /* *= 4 */
157 "subl %%eax, %%esp\n\t" /* make room for params */
158 "movl %%esp, %%edx\n\t"
159 "pushl %4\n\t"
160 "pushl %3\n\t"
161 "pushl %%edx\n\t"
162 "movl %6, %%eax\n\t"
163 "call *%%eax\n\t" /* copy params */
164 "addl $0xc, %%esp\n\t"
165 "movl %1, %%ecx\n\t"
166 "pushl %%ecx\n\t"
167 "movl (%%ecx), %%edx\n\t"
168 "movl %2, %%eax\n\t" /* function index */
169 "shl $2, %%eax\n\t" /* *= 4 */
170 "addl $8, %%eax\n\t" /* += 8 */
171 "addl %%eax, %%edx\n\t"
172 "call *(%%edx)\n\t" /* safe to not cleanup esp */
173 "movl %%eax, %0"
174 : "=g" (result) /* %0 */
175 : "g" (that), /* %1 */
176 "g" (index), /* %2 */
177 "g" (paramCount), /* %3 */
178 "g" (params), /* %4 */
179 "g" (fn_count), /* %5 */
180 "g" (fn_copy) /* %6 */
181 : "ax", "cx", "dx", "memory"
182 );
183
184 return result;
185 }
186
187 #endif
188 /***************************************************************************/
189
190 int main()
191 {
192 nsXPCVariant params1[2] = {1,2};
193 nsXPCVariant params2[2] = {2,4};
194 nsXPCVariant params3[2] = {3,6};
195
196 foo* a = new bar();
197
198 // printf("calling via C++...\n");
199 // docall(a, 12, 24);
200
201 printf("calling via ASM...\n");
202 DoInvoke(a, 1, 2, params1);
203 DoInvoke(a, 2, 2, params2);
204 DoInvoke(a, 3, 2, params3);
205
206 return 0;
207 }

mercurial