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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial